# Haskell/Next steps

This chapter introduces *pattern matching* and two new pieces of syntax: `if`

expressions and `let`

bindings.

## if / then / elseEdit

Haskell syntax supports garden-variety conditional expressions of the form *if... then... else...* . For instance, consider a function that returns `(-1)`

if its argument is less than `0`

; `0`

if its argument *is* `0`

; and `1`

if its argument is greater than `0`

. The predefined `signum`

function does that job already; but for the sake of illustration, let's define a version of our own:

**Example:** The signum function.

```
mySignum x =
if x < 0
then -1
else if x > 0
then 1
else 0
```

You can experiment with this:

*Main> mySignum 5 1 *Main> mySignum 0 0 *Main> mySignum (5 - 10) -1 *Main> mySignum (-1) -1

The parentheses around "-1" in the last example are required; if missing, Haskell will think that you are trying to subtract `1`

from `mySignum`

(which would give a type error).

In an if/then/else construct, first the condition (in this case `x < 0`

) is evaluated. If it results `True`

, the whole construct evaluates to the ` then` expression; otherwise (if the condition is

`False`

), the construct evaluates to the `expression. All of that is pretty intuitive. If you have programmed in an imperative language before, however, it might seem surprising to know that Haskell always requires`

**else***both*a

**then***and*an

`clause. The construct has to result in a value in both cases and, specifically, a value of the same type in both cases.`

**else**Function definitions using if / then / else like the one above can be rewritten using Guards.

**Example:** From if to guards

```
mySignum x
| x < 0 = -1
| x > 0 = 1
| otherwise = 0
```

Similarly, the absolute value function defined in Truth values can be rendered with an if/then/else:

**Example:** From guards to if

```
absolute x =
if x < 0
then -x
else x
```

Why use if/then/else versus guards? As you will see with later examples and in your own programming, either way of handling conditionals may be more readable or convenient depending on the circumstances. In many cases, both options work equally well.

## Introducing pattern matchingEdit

Consider a program which tracks statistics from a racing competition in which racers receive points based on their classification in each race, the scoring rules being:

- 10 points for the winner;
- 6 for second-placed;
- 4 for third-placed;
- 3 for fourth-placed;
- 2 for fifth-placed;
- 1 for sixth-placed;
- no points for other racers.

We can write a simple function which takes a classification (represented by an integer number: `1`

for first place, etc.^{[1]}) and returns how many points were earned. One possible solution uses if/then/else:

**Example:** Computing points with if/then/else

```
pts :: Int -> Int
pts x =
if x == 1
then 10
else if x == 2
then 6
else if x == 3
then 4
else if x == 4
then 3
else if x == 5
then 2
else if x == 6
then 1
else 0
```

Yuck! Admittedly, it wouldn't look this hideous had we used guards instead of if/then/else, but it still would be tedious to write (and read!) all those equality tests. We can do better, though:

**Example:** Computing points with a piece-wise definition

```
pts :: Int -> Int
pts 1 = 10
pts 2 = 6
pts 3 = 4
pts 4 = 3
pts 5 = 2
pts 6 = 1
pts _ = 0
```

*Much* better. However, even though defining `pts`

in this style (which we will arbitrarily call *piece-wise definition* from now on) shows to a reader of the code what the function does in a clear way, the syntax looks odd given what we have seen of Haskell so far. Why are there seven equations for `pts`

? What are those numbers doing in their left-hand sides? What about variable arguments?

This feature of Haskell is called *pattern matching*. When we call `pts`

, the argument is *matched* against the numbers on the left side of each of the equations, which in turn are the *patterns*. The matching is done in the order we wrote the equations. First, the argument is matched against the `1`

in the first equation. If the argument is indeed `1`

, we have a match and the first equation is used; so `pts 1`

evaluates to `10`

as expected. Otherwise, the other equations are tried in order following the same procedure. The final one, though, is rather different: the `_`

is a special pattern, often called a "wildcard", that might be read as "whatever": it matches with anything; and therefore if the argument doesn't match any of the previous patterns `pts`

will return zero.

As for the lack of `x`

or any other variable standing for the argument, we simply don't need that to write the definitions. All possible return values are constants. Besides, variables are used to express relationships on the right side of the definition, so the `x`

is unnecessary in our `pts`

function.

However, we could use a variable to make `pts`

even more concise. The points given to a racer decrease regularly from third place to sixth place, at a rate of one point per position. After noticing that, we can eliminate three of the seven equations as follows:

**Example:** Mixing styles

```
pts :: Int -> Int
pts 1 = 10
pts 2 = 6
pts x
| x <= 6 = 7 - x
| otherwise = 0
```

So, we can mix both styles of definitions. In fact, when we write `pts x`

in the left side of an equation we are using pattern matching too! As a pattern, the `x`

(or any other variable name) matches anything just like `_`

; the only difference being that it also gives us a name to use on the right side (which, in this case, is necessary to write `7 - x`

).

Exercises |
---|

We cheated a little when moving from the second version of `pts` to the third one: they do not do exactly the same thing. Can you spot what the difference is? |

Beyond integers, pattern matching works with values of various other types. One handy example is booleans. For instance, the `(||)`

logical-or operator we met in Truth values could be defined as:

**Example:** `(||)`

```
(||) :: Bool -> Bool -> Bool
False || False = False
_ || _ = True
```

Or:

**Example:** `(||)`

, done another way

```
(||) :: Bool -> Bool -> Bool
True || _ = True
False || y = y
```

When matching two or more arguments at once, the equation will only be used if all of them match.

Now, let's discuss a few things that might go wrong when using pattern matching:

- If we put a pattern which matches anything (such as the final patterns in each of the
`pts`

example)*before*the more specific ones the latter will be ignored. GHC(i) will typically warn us that "Pattern match(es) are overlapped" in such cases. - If no patterns match, an error will be triggered. Generally, it is a good idea to ensure the patterns cover all cases, in the same way that the
`otherwise`

guard is not mandatory but highly recommended. - Finally, while you can play around with various ways of (re)defining
`(&&),`

^{[2]}here is one version that will*not*work:

```
(&&) :: Bool -> Bool -> Bool
x && x = x -- oops!
_ && _ = False
```

- The program won't test whether the arguments are equal just because we happened to use the same name for both. As far as the matching goes, we could just as well have written
`_ && _`

in the first case. And even worse: because we gave the same name to both arguments, GHC(i) will refuse the function due to "Conflicting definitions for `x'".

## Tuple and list patternsEdit

While the examples above show that pattern matching helps in writing more elegant code, that does not explain why it is so important. So, let's consider the problem of writing a definition for `fst`

, the function which extracts the first element of a pair. At this point, that appears to be an impossible task, as the only way of accessing the first value of the pair is by using `fst`

itself... The following function, however, does the same thing as `fst`

(confirm it in GHCi):

**Example:** A definition for `fst`

```
fst' :: (a, b) -> a
fst' (x, _) = x
```

It's magic! Instead of using a regular variable in the left side of the equation, we specified the argument with the *pattern* of the 2-tuple - that is, `(,)`

- filled with a variable and the `_`

pattern. Then the variable was automatically associated with the first component of the tuple, and we used it to write the right side of the equation. The definition of `snd`

is, of course, analogous.

Furthermore, the trick demonstrated above can be done with lists as well. Here are the actual definitions of `head`

and `tail`

:

**Example:** `head`

, `tail`

and patterns

```
head :: [a] -> a
head (x:_) = x
head [] = error "Prelude.head: empty list"
tail :: [a] -> [a]
tail (_:xs) = xs
tail [] = error "Prelude.tail: empty list"
```

The only essential change in relation to the previous example was replacing `(,)`

with the pattern of the cons operator `(:)`

. These functions also have an equation using the pattern of the empty list, `[]`

; however, since empty lists have no head or tail there is nothing to do other than use `error`

to print a prettier error message.

In summary, the power of pattern matching comes from its use in accessing the parts of a complex value. Pattern matching on lists, in particular, will be extensively deployed in Recursion and the chapters that follow it. Later on, we will explore what is happening behind this seemingly magical feature.

`let` bindingsEdit

To conclude this chapter, a brief word about `let`

bindings (an alternative to `where`

clauses for making local declarations). For instance, take the problem of finding the roots of a polynomial of the form (in other words, the solution to a second degree equation — think back to your middle school math courses). Its solutions are given by:

- .

We could write the following function to compute the two values of :

```
roots a b c =
((-b + sqrt(b * b - 4 * a * c)) / (2 * a),
(-b - sqrt(b * b - 4 * a * c)) / (2 * a))
```

Writing the `sqrt(b * b - 4 * a * c)`

term in both cases is annoying, though; we can use a local binding instead, using either `where`

or, as will be demonstrated below, a `let`

declaration:

```
roots a b c =
let sdisc = sqrt (b * b - 4 * a * c)
in ((-b + sdisc) / (2 * a),
(-b - sdisc) / (2 * a))
```

We put the `let`

keyword before the declaration, and then use `in`

to signal we are returning to the "main" body of the function. It is possible to put multiple declarations inside a single `let`

...`in`

block — just make sure they are indented the same amount or there will be syntax errors:

```
roots a b c =
let sdisc = sqrt (b * b - 4 * a * c)
twice_a = 2 * a
in ((-b + sdisc) / twice_a,
(-b - sdisc) / twice_a)
```

Because indentation matters syntactically in Haskell, you need to be careful about whether you are using tabs or spaces. By far the best solution is to configure your text editor to insert two or four spaces in place of tabs. If you insist on keeping tabs as distinct, at least ensure that your tabs always have the same length. |

*Note*

The Indentation chapter has a full account of indentation rules.

## Notes

- ↑ Here we will not be much worried about what happens if a nonsensical value (say,
`(-4)`

) is passed to the function. In general, however, it is a good idea to give some thought to such "strange" cases, in order to avoid nasty surprises down the road. - ↑ If you are going to experiment with it in GHCi, call your version something else to avoid a name clash; say, (&!&).