`(n \`mod\` 2 == 0)`

is evaluated; it is `False` since `n = 3` does not result in a remainder of `0` when divided by `2`. `otherwise` is just a convenient synonym for `True`, so the second
guard is chosen, and the result of `hailstone 3` is thus `3 * 3 + 1 = 10`.
As a more complex (but more contrived) example:
```active haskell
foo :: Integer -> Integer
foo 0 = 16
foo 1
| "Haskell" > "C++" = 3
| otherwise = 4
foo n
| n < 0 = 0
| n `mod` 17 == 2 = -43
| otherwise = n + 3
main = print [foo (-3), foo 0, foo 1, foo 36, foo 38]
```
As a final note about Boolean expressions and guards, suppose we wanted to abstract out the test of
evenness used in defining `hailstone`. A first attempt is shown below:
```active haskell
isEven :: Integer -> Bool
isEven n
| n `mod` 2 == 0 = True
| otherwise = False
main = print [isEven 2, isEven 5]
```
This _works_, but is much too complicated. Can you see why?
@@@
The code returns `True` or `False`, depending whether `n \`mod\` 2 == 0`

is `True` or `False`. It would have been much simpler to write it as
```haskell
isEven : Integer -> Bool
isEven n = n `mod` 2 == 0
```
@@@
# Pairs
We can pair things together like so:
```haskell
p :: (Int, Char)
p = (3, 'x')
```
Notice that the (x,y) notation is used both for the _type_ of a pair and a pair _value_.
The elements of a pair can be extracted again with _pattern matching_:
```active haskell
sumPair :: (Int, Int) -> Int
sumPair (x,y) = x + y
main = print (sumPair (3,4))
```
Haskell also has triples, quadruples, ... but you should never use them. As we’ll see in the next lesson, there are much better ways to package three or more pieces of information together.
# Using functions
To apply a function to some arguments, just list the arguments after the function, separated by spaces, like this:
```active haskell
f x y z = x + y + z
main = print (f 3 17 8)
```
The above example applies the function `f` to the three arguments `3`, `17`, and `8`.
Note that function application has higher precedence than any infix operators! So it would be incorrect to write `f 3 n+1 7` if you intend to pass `n+1` as the second argument to `f`, because this parses as `(f 3 n) + (1 7)`. Instead, one must write `f 3 (n+1) 7`.
# Constructing Lists
The simplest possible list is the empty list:
```haskell
emptyList = []
```
Other lists are built up from the empty list using the _cons_ operator, `(:)`. Cons takes an element and a list, and produces a new list with the element prepended to the front.
```haskell
a = 1 : []
b = 3 : (1 : [])
c = [2,3,4] == 2 : 3 : 4 : []
```
We can see that `[2,3,4]` notation is just convenient shorthand for `2 : 3 : 4 : []`. Note also that these are really singly-linked lists, and **not** arrays.
``` active haskell
-- /show
hailstone :: Integer -> Integer
hailstone n
| n `mod` 2 == 0 = n `div` 2
| otherwise = 3 * n + 1
-- show
hailstoneSeq :: Integer -> [Integer]
hailstoneSeq 1 = [1]
hailstoneSeq n = n : hailstoneSeq (hailstone n)
main = print (hailstoneSeq 5)
```
We stop the hailstone sequence when we reach 1. The hailstone sequence for a general n consists of n
itself, followed by the hailstone sequence for `hailstone n`, that is, the number obtained by applying the hailstone transformation once to `n`.
# Functions on Lists
We can write functions on lists using _pattern matching_.
```active haskell
-- Compute the length of a list of Integers
intListLength :: [Integer] -> Integer
intListLength [] = 0
intListLength (x:xs) = 1 + intListLength xs
main = print (intListLength [1,2,3,4,5])
```
The first clause says that the length of an empty list is 0. The second clause says that if the input list looks like `(x:xs)`, that is, a first element xconsed onto a remaining list `xs`, then the length is one more than the length of `xs`.
Since we don’t use `x` at all we could also replace it by an underscore: `intListLength (_:xs) = 1 + intListLength xs`.
We can also use nested patterns:
```active haskell
sumEveryTwo :: [Integer] -> [Integer]
sumEveryTwo [] = [] -- Do nothing to the empty list
sumEveryTwo (x:[]) = [] -- Do nothing to lists with a single element
sumEveryTwo (x:(y:zs)) = (x + y) : sumEveryTwo zs
main = print (sumEveryTwo [1,2,3,4,5,6,7,8])
```
Note how the last clause matches a list starting with `x` and followed by... a list starting with `y` and followed by the list `zs`. We don’t actually need the extra parentheses, so `sumEveryTwo (x:y:zs) = ...` would be equivalent.
# Combining Functions
It’s good Haskell style to build up more complex functions by combining many simple ones.
```active haskell
hailstone :: Integer -> Integer
hailstone n
| n `mod` 2 == 0 = n `div` 2
| otherwise = 3 * n + 1
hailstoneSeq :: Integer -> [Integer]
hailstoneSeq 1 = [1]
hailstoneSeq n = n : hailstoneSeq (hailstone n)
-- Compute the length of a list of Integers
intListLength :: [Integer] -> Integer
intListLength [] = 0
intListLength (x:xs) = 1 + intListLength xs
-- show
-- The number of hailstone steps needed to reach 1 from a given number
hailstoneLen :: Integer -> Integer
hailstoneLen n = intListLength (hailstoneSeq n) - 1
main = print (hailstoneLen 5)
```
This may seem inefficient to you: it generates the entire hailstone sequence first and then finds its length, which wastes lots of memory... doesn’t it? Actually, it doesn’t! Because of Haskell’s lazy evaluation, each element of the sequence is only generated as needed, so the sequence generation and list length calculation are interleaved. The whole computation uses only O(1) memory, no matter how long the sequence. [Actually, this is a tiny white lie, but explaining why (and how to fix it) will have to wait a few lessons.]
# A Word About Error Messages
Actually, six:
## Don't be scared of error messages!
GHC’s error messages can be rather long and (seemingly) scary. However, usually they’re long not because they are obscure, but because they contain a lot of useful information! Here’s an example:
```
Prelude> 'x' ++ "foo"
` Couldn't match expected type \`[Char]' with actual type \`Char' `

. This means that something was expected to have a list type, but actually had type `Char`. What something? The next line tells us: it’s the first argument of `(++)` which is at fault, namely, `'x'`. The next lines go on to give us a bit more context.
Now we can see what the problem is: clearly `'x'` has type `Char`, as the first line said. Why would it be expected to have a list type? Well, because it is used as an argument to `(++)`, which takes a list as its first argument.
When you get a huge error message, resist your initial impulse to run away; take a deep breath; and read it carefully. You won’t necessarily understand the entire thing, but you will probably learn a lot, and you may just get enough information to figure out what the problem is.