This is the fifth article of a series on the functional language Haskell for beginners

Thank you for joining us for the fifth part of our Haskell series, you will find the previous article here where I explain tuples and pattern matching.

In this article we are going to continue a little bit more on pattern matching and then discover guards.

Lists and Pattern Matching

Pattern matching is a great feature in Haskell, on the previous article we applied it on a simple value and on tuples, but this is most of the times used on lists.

Let's try it on something simple, we are going to write a function which determines if a list is empty or not:

``````-- Let's create a new file pattern.hs and paste this :
isEmpty :: [a] -> Bool
isEmpty [] = True
isEmpty list = False
``````

So we create a function called `isEmpty` which takes as a parameter a list with a type variable `a` (meaning our list can contain anything, we do not really care here) and will return a boolean (True = empty).

We define 2 patterns here:

• `[]`: This represents an empty list
• `list`: This is the name of our parameter for `[a]` from the function definition. We put this one last, otherwise we would always "fall" into this condition.

Let's try it out in GHCI:

``````Prelude> :l pattern.hs
[1 of 1] Compiling Main             ( pattern.hs, interpreted )
*Main> a = []
*Main> b = [1, 2, 3]
*Main> isEmpty a
True
*Main> isEmpty b
False``````

Everything goes as expected, neat.

If you remember the second article, we were discovering lists for the first time and found out that a helper was available to get the first (`head`) element of a list. Let's try to rewrite it using pattern matching:

``````theFirst :: [a] -> a
theFirst (x:_) = x``````

So we create a function called `theFirst` which takes as a parameter a list with a type variable `a` and will return the first element of the same type `a`.

We define a single pattern here `(x:_)` which deconstructs the lists into:

• `x` as the first element of the list (`x` and `xs` are frequently used in list based pattern matching in Haskell even though anything else can be used).
• `_` is the remaining of the list and as we discussed on the previous article an underscore in Haskell is a convention for an unused part of a pattern.

Let's try it out in GHCI:

``````Prelude> :l pattern.hs
[1 of 1] Compiling Main             ( pattern.hs, interpreted )
*Main> b = [1, 2, 3]
*Main> theFirst b
1
``````

Great, we got our first element from the list `b`. But, what would happen on an empty list ?

``````*Main> a = []
*Main> theFirst a
*** Exception: pattern.hs:7:1-18: Non-exhaustive patterns in function theFirst``````

Yep, we forgot to take in account the case where a list would be empty and GHCI throws a pretty explicit exception. Let's try to address that:

``````-- This is the amended version of theFirst
theFirst :: [a] -> a
theFirst [] = error "Sorry, empty lists are not supported"
theFirst (x:_) = x``````

We added a new line with a pattern matching an empty array and we used `error` to throw a runtime error with a message. Let's try it out:

``````Prelude> :l pattern.hs
[1 of 1] Compiling Main             ( pattern.hs, interpreted )
*Main> b = []
*Main> theFirst b
*** Exception: Sorry, empty lists are not supported
CallStack (from HasCallStack):
error, called at pattern.hs:7:15 in main:Main
``````

The program still crashes but at least, it was our decision. If it makes you curious about what is the actual behavior of `head` , there it is:

``````*Main> head b

As you can see `head` throws a runtime error as well.

Guards

The concept of guards is also common in the functional programming world, we talked about it in our Elixir article. The idea with guards is closer to the classic if/else scenarios where we test if a value is True or False, whereas pattern matching deconstructs data and binds it to variables inside the function (Remember `theFirst (x:_) = x`, automatically the first element was bound to `x`).

To make it clearer let's try to rewrite our function `isItTheWeekEndAlready` we wrote in the previous article using guards:

``````-- Let's paste this in a new file guards.hs
| day == 0 || day == 6 = True
| otherwise = False``````

So a few things to note:

• It is really similar to the if/else version we wrote
• We declare the variable name `day` on top so we can use it the function body (which we do not do in pattern matching for instance)
• There is a "catch all" called `otherwise` (again, like an `else` in the good old if/else approach)

Let's try to run it:

``````*Main> :l guards.hs
[1 of 1] Compiling Main             ( guards.hs, interpreted )
False
True
True``````

Looks good.

There's one more thing which is pretty helpful when using guards called `where`. It allows us to define a context (using variables) once and use it in the guards. Let's demonstrate it in a function which calculates the ratio of the number of breakfasts you should have eaten in a year (we will assume that everyone understands it is the most important meal of the day). You will get a message based on said ratio:

``````-- Let's add this to guards.hs
numberOfBreakfasts :: Float -> String
numberOfBreakfasts nb
| ratio < 0.5 = "Oh no"
| ratio < 1 = "Not bad"
| ratio == 1 = "Perfect"
| otherwise = "Tell me your secret"
where ratio = nb / 365``````

As you can see, instead of writing three time this `nb / 365` in each guard, we used `where` to define it once. Let's try it out:

``````*Main> :l guards.hs
[1 of 1] Compiling Main             ( guards.hs, interpreted )
*Main> numberOfBreakfasts 100
"Oh no"
*Main> numberOfBreakfasts 200
*Main> numberOfBreakfasts 365
"Perfect"
*Main> numberOfBreakfasts 500