# Happy Learn Haskell Tutorial Vol 1

Written and illustrated by GetContented.

Published on 2017-02-12.

## Contents

Previous chapter: 12. How To Write Programs
13. At The Zoo
... 13.1. Sum Types
... 13.2. Pattern Matching with Sum Types
... 13.3. More Recursion
... 13.4. What is Currying?
... 13.5. The Finished Program
... 13.6. Homework
Next chapter: 14. Cats and Houses

# 13. At The Zoo 🔗

In this chapter, we'll make a small program that tells a Zoo owner what advice to take for each animal in the Zoo if it escapes. In the process, we’ll introduce you to an awesome feature of Haskell: the ability to make your own data types, and values of those types.

We’ll have a value for each of a number of animals, and we’ll also have a list of animals which we’ll call a Zoo.

To do this, we’ll use the `data` keyword which creates a new data type, and specifies all the values it can possibly be. Another name for these kinds of types is a sum type, because the values of the type “summed together” make up the whole type.

## 13.1. Sum Types 🔗

So, let’s see a sum type.

``````
data Animal = Giraffe
| Elephant
| Tiger
| Flea
``````

We’re saying that we want Haskell to make a new type, named `Animal`. We’re also saying that the data for the `Animal` type can be any one of `Giraffe`, `Elephant`, `Tiger` or `Flea`, but nothing else. These values are also called value constructors, even though they’re each only able to construct the value that they are. We’ll see why more later.

Let’s see the type for `Zoo` next:

``````
type Zoo = [Animal]
``````

Pretty simple. A `Zoo` is an `Animal` list. You might recognise this is just a type synonym, for our convenience and documentation. Next we’ll see a definition for a `Zoo`:

``````
localZoo :: Zoo
localZoo = [ Elephant
, Tiger
, Tiger
, Giraffe
, Elephant
]
``````

Ok, the `Zoo` named `localZoo` has some `Animal` values in it. Let’s put all of this together and add a function that uses a `case` expression to give some advice when a particular animal escapes.

## 13.2. Pattern Matching with Sum Types 🔗

Below, we have a function that takes a single `Animal`, and returns a piece of advice as a `String`, for when that `Animal` escapes. Looking at the `case` expression, you can see it’s matching against the values of the `Animal` data type.

``````
data Animal = Giraffe
| Elephant
| Tiger
| Flea

type Zoo = [Animal]

localZoo :: Zoo
localZoo = [ Elephant
, Tiger
, Tiger
, Giraffe
, Elephant
]

case animal of
Giraffe   -> "Look up"
Elephant  -> "Ear to the ground"
Tiger     -> "Check the morgues"
Flea      -> "Don't worry"
``````

If you remember how `case` expressions work, the `animal` variable is checked against each of the left hand side patterns to see if it maches, and if it does, the right hand side expression (here a `String` value) will be returned.

Do you notice that there’s no default case, usually marked with an underscore? That’s because we know this function is total already, because it has one item for each of the possible data values of the `Animal` type, so there’s nothing left to catch for a default case.

## 13.3. More Recursion 🔗

Next we’re going to look at a function that takes a `Zoo`, and returns a list of all the advice for when all the animals in that `Zoo` escape, by using the `adviceOnEscape` function and recursion.

``````
``````

Maybe you recognise this code as recursion, and similar to the previous chapters, in that it has a kind of a “folding” shape.

It’s a little bit different, though, because we can’t just use `(:)` as the folding function, as we’re also applying `adviceOnEscape` to each item as we fold them together into the new list.

In fact, in this case while we could think of it as folding the list into another list, we’re not really folding the list down to a single value, we’re just applying a function across all the elements of the list. Another way to look at it is that we’re making a new list that is just like the old one with a function applied to all its elements.

We could try a fold to do this, but we’d have to extract both the `adviceOnEscape` and the `(:)` out into a single folding function. Let’s see what that would look like, and we’ll also see some more local binding using a `where` clause while we do so:

``````

``````

When we look at them together, we can see that we’re worse off that before! `foldr` was supposed to help us write less code, but it actually has us producing more! This should be telling us something: that `foldr` is not the right abstraction to use here.

We included a function called `addAdviceForAnimal`, which we used as our folding function. As we’ve seen before, the `where` clause handily makes definitions below it available to the `adviceOnZooEscape’` function. This is called local scoping. The `where` clause makes the definitions within it only available within the expressions that appear above it. We’ll see more of this soon.

So, it turns out that there is actually a function whose job it is to do what we want here: take a list of `a` and turn it into a list of `b`, using a function of type `(a -> b)` (which we could call the mapping function). It’s called `map :: (a -> b) -> [a] -> [b]`, because it keeps the “shape” of the list, but through across all its values and applies the mapping function to each item, producing a new list of mapped values as it does. Let’s see it in action:

``````
``````

Really nice, and clean looking. The map function is called a higher order function because it takes a function as an argument, so it’s an order higher than normal functions that just take values.

Also, we can simplify this by not mentioning the argument to the function. It still has one, but it’s implied by the types of the function and `map`. Observe:

``````
``````

You give a 2-argument function only 1 argument, and this turns it into a 1-argument function! Haskell rocks!

We’re defining `adviceOnZooEscape` as a function of one argument without mentioning the argument it takes. We can do this because we’re also not mentioning the second argument of `map`. Another way to say this is that we’ve made an expression of `map`, a 2-argument function, and we’ve only given it one of its arguments, so the result is a function of one argument.

## 13.4. What is Currying? 🔗

You may remember that a function `plus :: Int -> Int -> Int` can be defined as `plus x y = x + y`, or it can be defined as `plus = \x -> (\y -> x + y)`, they’re identical to Haskell, because a 2-argument function is actually a function that returns a function of one argument. If we give `plus` one `Int` value, it will bind that value to `x`, and return the inner function. Let’s see a defition for `plus5`: `plus5 = plus 5`. This will return the function `y -> 5 + y`. This way of defining multiple argument functions is called currying. It’s named after one of the men who invented it, Haskell Curry. Yes, Haskell is named after him.

## 13.5. The Finished Program 🔗

Next we’ll see how this connects up to a comma-separating function, and a definition for main to finish the program, and we’ll use another where clause:

``````
import qualified Data.List as L

data Animal = Giraffe
| Elephant
| Tiger
| Flea
type Zoo = [Animal]

localZoo :: Zoo
localZoo = [ Elephant
, Tiger
, Tiger
, Giraffe
, Elephant
]

case animal of
Giraffe   -> "Look up"
Elephant  -> "Ear to the ground"
Tiger     -> "Check the morgues"
Flea      -> "Don't worry"

joinedWithCommasBetween :: [String] -> String
joinedWithCommasBetween []     = ""
joinedWithCommasBetween [x]    = x
joinedWithCommasBetween (x:xs) =
x ++ ", " ++ joinedWithCommasBetween xs

main :: IO ()
main = putStrLn stringToPrint
where
stringToPrint = L.intercalate ", " advices
``````

We have some new things here. Firstly, we have a qualified import. Importing is how we can include other code to use in ours. Making it qualified means all the imports actually sit underneath a special name (we’re calling it `L` here), and so as you can see, when we want to use the `intercalate` function below, in main’s definition, we have to write `L.intercalate` to tell it we mean the one inside the `Data.List` module.

The second thing to note is that we’ve included a `joinedWithCommasBetween` function. We’re not actually using it here. We’ve seen it before, but it’s identical to the function obtained by providing the `intercalate` function from `Data.List` with a `", "` value, except that it also works on any Lists, not just `[String]`, so we included the definition so you can understand one way `intercalate` could work.

The type of `intercalate` is `[a] -> [[a]] -> [a]`. Because the `String` type is actually just a synonym for `[Char]`, this fits if “`a`” is `Char`. (It fits as `[Char] -> [[Char]] -> [Char]` which is the same as `String -> [String] -> String`).

The type of the expression `intercalate ", "` is `[String] -> String`, same as `joinedWithCommasBetween`.

We’re using two lines in a where clause inside our `main`, this time. There is `advices`, which uses `adviceOnZooEscape` to build a list of pieces of advice using `localZoo`, and `stringToPrint` which uses `intercalate` and `advices` to create a string that is passed to `putStrLn`.

## 13.6. Homework 🔗

Your homework is to write a program that prints out the `String "Hello there"`, and then change it to print out your name. Try to remember what you have to write and not look at the book while you’re writing your program. Only once you’ve finished, check your work against the book, and by running the program.

Once you’ve done that, do it again, but make the program print out your mother’s name.

Once you’ve done that, do it again this time with your favourite colour.

Do this by both using a separate definition for the `String`, as well as putting the `String` directly in.

You should do this as many times as you need to with different `String` values, not looking until after, so that you can write any program that prints out a `String` without looking anything up. Make sure you’re writing the type signatures, as well.

Now it’s time to pat yourself on the back, and take a break - you’ve written your first Haskell programs! Well done.

At this point, you know how simple function application works. You take a value, and you put it to the right of a function, and this expression in total is equal to the returned value.

Why did we wait so long before recommending you begin to write code? Simply, we want you to be very comfortable with seeing, reading and understanding things you write before you begin to write them.

Also, Volume 2 is now in beta and being written! Show your support and register your interest at its Leanpub site.