﻿

## = ` quickSort ` 的背後

### So Let's Get Down To It!

```-- 空表，什么都不做
-- 这个是递归的初始条件
quickSort [] = []

-- 只有一个元素的时候，也不需要排序
-- 实际上，第三个已经包含这一部分的处理了
--  但我们要一步一步来
quickSort [x] = [x]

-- 整个排序的关键
-- 拿出一个元素作为 “支点”  ，剩下的去排序
-- 别忘了支点是在表的中间 ！
quickSort (x : xs) = (quickSort less) ++ (x : equal) ++ (quickSort more)
where less = filter (< x) xs
equal = filter (== x) xs
more = filter (> x) xs
```

## 現在，我們要怎麼利用它 ？

```dictionary = ["I", "have", "a", "thing", "for", "Linux"]
```

```["I", "Linux", "a", "for", "have", "thing"]
```

## 修改我們原來的代碼

What we need to do is to factor out the comparisons `quickSort` makes. We need to provide `quickSort` with a function that compares two elements, and gives an `Ordering`, and as you can imagine, an `Ordering` is any of `LT, EQ, GT`.

To sort in the descending order, we supply `quickSort` with a function that returns the opposite of the usual `Ordering`. For the case-insensitive sort, we may need to define the function ourselves. By all means, we want to make `quickSort` applicable to all such functions so that we don't end up writing it over and over again, each time with only minor changes.

## `quickSort`, Take Two

Our `quickSort` will take two things this time: first, the comparison function, and second, the list to sort.

A comparison function will be a function that takes two things, say, `x` and `y`, and compares them. If `x` is less than `y` (according to the criteria we want to implement by this function), then the value will be `LT`. If they are equal (well, equal with respect to the comparison, we want "Linux" and "linux" to be equal when we are dealing with the insensitive case), we will have `EQ`. The remaining case gives us `GT` (pronounced: greater than, for obvious reasons).

```-- no matter how we compare two things
-- the first two equations should not change
-- they need to accept the comparison function though
-- but the result doesn't need it
quickSort _ [] = []
quickSort _ [x] = [x]

-- we are in a more general setting now
-- but the changes are worth it!
-- c is the comparison function
quickSort c (x : xs) = (quickSort c less) ++ (x : equal) ++ (quickSort c more)
where less  = filter (\y -> y `c` x == LT) xs
equal = filter (\y -> y `c` x == EQ) xs
more  = filter (\y -> y `c` x == GT) xs
```

Cool!

 註解 Almost all the basic data types in Haskell are members of the `Ord` class. This class defines an ordering, the "natural" one. The functions (or, operators, in this case) `(<)`, `(==)` or `(>)` provide shortcuts to the `compare` function each type defines. When we want to use the natural ordering as defined by the types themselves, the above code can be written using those operators, as we did last time. In fact, that makes for much clearer style; however, we wrote it the long way just to make the relationship between sorting and comparing more evident.

## But What Did We Gain?

Reuse. We can reuse `quickSort` to serve different purposes.

```-- the usual ordering
-- uses the compare function from the Ord class
usual = compare

-- the descending ordering, note we flip the order of the arguments to compare
descending x y = compare y x

-- the case-insensitive version is left as an exercise!
insensitive = ...
-- can you think of anything without making a very big list of all possible cases?
```

And we are done!

`quickSort usual dictionary`

should, then, give

`["I", "Linux", "a", "for", "have", "thing"]`

The comparison is just `compare` from the `Ord` class. This was our `quickSort`, before the tweaking.

`quickSort descending dictionary`

now gives

`["thing", "have", "for", "a", "Linux", "I"]`

And finally,

`quickSort insensitive dictionary`

gives

`["a", "for", "have", "I", "Linux", "thing"]`

Exactly what we wanted!

Write `insensitive`, such that `quickSort insensitive dictionary` gives `["a", "for", "have", "I", "Linux", "thing"]`

## Higher-Order Functions and Types

Our `quickSort` has type `(a -> a -> Ordering) -> [a] -> [a]`.

Most of the time, the type of a higher-order function provides a good guideline about how to use it. A straightforward way of reading the type signature would be, "`quickSort` takes a function that gives an ordering of `a`s, and a list of `a`s, to give a list of `a`s". It is then natural to guess that the function sorts the list respecting the given ordering function.

Note that the parentheses surrounding `a -> a -> Ordering` is mandatory. It says that `a -> a -> Ordering` altogether form a single argument, an argument that happens to be a function. What happens if we omit the parentheses? We would get a function of type `a -> a -> Ordering -> [a] -> [a]`, which accepts four arguments instead of the desired two (`a -> a -> Ordering` and `[a]`). Furthermore none of the four arguments, neither `a` nor `Ordering` nor `[a]` are functions, so omitting the parentheses would give us something that isn't a higher order function.

Furthermore, it's worth noting that the `->` operator is right-associative, which means that `a -> a -> Ordering -> [a] -> [a]` means the same thing as `a -> (a -> (Ordering -> ([a] -> [a])))`. We really must insist that the `a -> a -> Ordering` be clumped together by writing those parentheses... but wait... if `->` is right-associative, wouldn't that mean that the correct signature `(a -> a -> Ordering) -> [a] -> [a]` actually means... `(a -> a -> Ordering) -> ([a] -> [a])`?

Is that really what we want?

If you think about it, we're trying to build a function that takes two arguments, a function and a list, returning a list. Instead, what this type signature is telling us is that our function takes one argument (a function) and returns another function. That is profoundly odd... but if you're lucky, it might also strike you as being profoundly beautiful. Functions in multiple arguments are fundamentally the same thing as functions that take one argument and give another function back. It's OK if you're not entirely convinced. We'll go into a little bit more detail below and then show how something like this can be turned to our advantage.

The following exercise combines what you have learned about higher order functions, recursion and IO. We are going to recreate what programmers from more popular languages call a "for loop". Implement a function
```for :: a -> (a->Bool) -> (a->a) -> (a-> IO ()) -> IO ()
for i p f job = -- ???```
An example of how this function would be used might be
`for 1 (<10) (+1) (print)`
which prints the numbers 1 to 9 on the screen.

Starting from an initial value `i`, the `for` executes `job i`. It then modifies this value `f i` and checks to see if the modified value satisfies some condition. If it doesn't, it stops; otherwise, the for loop continues, using the modified `f i` in place of `i`.

1. The paragraph above gives an imperative description of the for loop. What would a more functional description be?
2. Implement the for loop in Haskell.
3. Why does Haskell not have a for loop as part of the language, or in the standard library?

Some more challenging exercises you could try

1. What would be a more Haskell-like way of performing a task like 'print the list of numbers from 1 to 10'? Are there any problems with your solution?
2. Implement a function `sequenceIO :: [IO a] -> IO [a]`. Given a list of actions, this function runs each of the actions in order and returns all their results as a list.
3. Implement a function `mapIO :: (a -> IO b) -> [a] -> IO [b]` which given a function of type `a -> IO b` and a list of type `[a]`, runs that action on each item in the list, and returns the results.
This exercise was inspired from a blog post by osfameron. No peeking!

## Currying

I hope you followed the reasoning of the preceding chapter closely enough. If you haven't, you should, so give it another try.

Currying is a technique that lets you partially apply a multi-parameter function. When you do that, it remembers those given values, and waits for the remaining parameters.

Our `quickSort` takes two parameters, the comparison function, and the list. We can, by currying, construct variations of `quickSort` with a given comparison function. The variation just "remembers" the specific comparison, so you can apply it to the list, and it will sort the list using the that comparison function.

```descendingSort = quickSort descending
```

What is the type of descendingSort? `quickSort` was `(a -> a -> Ordering) -> [a] -> [a]`, and the comparison function `descending` was `a -> a -> Ordering`. Applying `quickSort` to `descending` (that is, applying it partially, we haven't specified the list in the definition) we get a function (our `descendingSort`) for which the first parameter is already given, so you can scratch that type out from the type of `quickSort`, and we are left with a simple `[a] -> [a]`. So we can apply this one to a list right away!

```descendingSort dictionary
```

gives us

```["thing", "have", "for", "a", "Linux", "I"]
```

It's rather neat. But is it useful? You bet it is. It is particularly useful as sections, you might notice. Currying often makes Haskell programs very concise. More than that, it often makes your intentions a lot clearer. Remember

```less = filter (< x) xs
```

from the first version of `quickSort`? You can read it aloud like "keep those in `xs` that are less than `x`". Although `(< x)` is just a shorthand for `(\y -> y < x)`, try reading that aloud!