# Happy Learn Haskell Tutorial Vol 1

Written and illustrated by GetContented.

Published on 2017-12-25.

## Contents

Previous chapter: 13. At The Zoo
14. Cats and Houses
... 14.1. Another Sum Type
... 14.2. Product Types and Algebraic Data Types
... 14.3. Pattern-Matching Product Types
... 14.4. Function Composition
... 14.5. Importing a Module
... 14.7. A Little Finding & Sorting
... 14.9. The Final Program
... 14.10. Homework
Next chapter: 15. Basic Output

# 14. Cats and Houses 🔗

Feline Crescent has ten houses on it. Each house has a cat of a different breed living in it. We’ll be seeing sections of programs that we’ll slowly build up to a program that finds the oldest of the cats on the street and prints out where they live, along with their age in equivalent human years.

## 14.1. Another Sum Type 🔗

First, let’s see a data type for cat breeds:

``````
data CatBreed =
Siamese | Persian | Bengal | Sphynx
| Burmese | Birman | RussianBlue
| NorwegianForest | CornishRex | MaineCoon
``````

If you remember, we know this sum type means we’re declaring a new type of data called `CatBreed`, and all the possible values are listed above.

## 14.2. Product Types and Algebraic Data Types 🔗

Next, we’ll see a data type for `Cat`. This is a new kind of data type called a product type. This lets us make values that combine more than one type. When we saw tuples, you may remember we said that there are better ways to combine multiple values into one value. Well, this is that better way. A `Cat` can have an `Age`, and a `Name`, and a breed (`CatBreed`).

``````
type Name = String
type Age = Integer
data Cat = Cat Name CatBreed Age
``````

This tells Haskell that `Cat` is a new type for data, and that it has only one value constructor. Both sum types and product types are examples of algebraic data types. You can have combinations of these types in the one type, which means you can have types that are sums of product types. We’ll see more of this later, so don’t worry too much about this for now. Algebra is another fancy word which just means a sort of language of combining elements together — in this case, we’re combining types. You probably know this word from Maths if you’ve studied it.

Our code also tells Haskell that `Cat` is the name of the value constructor, as well as the name of the type. So how does Haskell know when we’re talking about the type, and when we’re talking about the value? Well, by looking at the places we’re using it, it can use inference to work it out.

Notice the `Cat` type is defined as one single `Cat` data constructor, which has variable “slots” for the name, breed and age. This actually tells Haskell to make the value constructor function `Cat :: Name -> CatBreed -> Age -> Cat` and this can be used to make `Cat` values (which is why it’s called a data constructor), as well as pattern match for these values. Remember how `(:)` is a value constructor for the list type? Well, it’s the same thing at work here.

## 14.3. Pattern-Matching Product Types 🔗

Next we’ll see a product type for House:

``````
type HouseNumber = Int
data House = House HouseNumber Cat
``````

And a function to work out how old a cat is in human years:

``````
-- this is a commonly agreed upon
-- way to work out cat ages
humanAge :: Cat -> Age
humanAge (Cat _ _ catAge)
| catAge <= 0 = 0
| catAge == 1 = 15
| catAge == 2 = 25
| otherwise   = 25 + (catAge - 2) * 4
``````

We’re using a guard pattern to match all the possibilities here. Maybe you can remember that the `(<=)` operator means “is less than or equal to”. There is a similar operator for the other direction, too `(>=)` which means “is greater than or equal to”.

Notice that the first argument to humanAge is a `Cat`, a single value of the `Cat` type, but it’s being kind of “pulled apart” by the pattern match using the value constructor. This takes the first two fields of the `Cat` data type and ignores them (by matching them to “`_`” which as you might know by now, basically throws them away), and then binds a variable name to the age of the `Cat` called `catAge`, so the rest of the function can compare and do math with it.

Next we’ll see some data for a `street`, which will be a list of houses, and a couple of functions for working with that data:

``````
street :: [House]
street =
[ House 1 (Cat "George" Siamese 10)
, House 2 (Cat "Mr Bigglesworth" Persian 5)
, House 3 (Cat "Mr Tinkles" Birman 1)
, House 4 (Cat "Puddy" Burmese 3)
, House 5 (Cat "Tiger" Bengal 7)
, House 6 (Cat "The Ninja" RussianBlue 12)
, House 7 (Cat "Mr Tinklestein"
NorwegianForest
8)
, House 8 (Cat "Plain Cat" MaineCoon 9)
, House 9 (Cat "Shnooby" Sphynx 7)
, House 10 (Cat "Crazy Ears Sam"
CornishRex
3)
]

getCatFromHouse :: House -> Cat
getCatFromHouse (House _ c) = c

getHumanAgeOfCatFromHouse :: House -> Age
getHumanAgeOfCatFromHouse =
humanAge . getCatFromHouse
``````

So, `street` is a value whose type is `[House]`. The type of `House` says it has a single data constructor, also called `House` which takes two fields (`House :: HouseNumber -> Cat -> House`) and returns a `House` value. Each of these houses has an embedded `Cat` value in it constructed with the `Cat` data constructor which is building a `Cat` out of a `Name`, its `CatBreed`, and its `Age`.

Moving on from there, we know that every `House` must have a `Cat` in it if we look at the `House` type, so we see there’s a simple function that extracts the `Cat` value from a `House` value by using pattern matching (called `getCatFromHouse`).

## 14.4. Function Composition 🔗

The next function (`getHumanAgeOfCatFromHouse`) probably looks a little curious, because we’ve got a new operator in it named `(.)` which kind of glues two functions together. It turns them into a single function that does the same as calling the first one on the result of calling the second one. It’s called the function composition operator. We’ll talk more about this function later, but you can think of it as feeding the “output” of the function on the right into the “input” of the function on the left.

The type of `getHumanAgeOfCatFromHouse` is annotated to be `House -> Age`. As we just saw, `getCatFromHouse` takes a `House` and gives a `Cat`, and `humanAge` takes a `Cat` and gives an `Age`. So, if we somehow could chain or pipe them together (glue them at the `Cat`, so to speak!), then giving this new function a `House` value would give us back an `Age`. This is exactly what the `(.)` operator does to two functions: it chains them together to form a new one that does the work of both, as long as they have a common type between them.

Here’s another way to write that same relation by just using regular function application rather than function composition.

``````
getHumanAgeOfCatFromHouse :: House -> Age
getHumanAgeOfCatFromHouse h =
humanAge (getCatFromHouse h)
``````

We can see that we have to include a variable for the `House` value here, and we can see that we’re applying the function `getCatFromHouse` to the `House`, and then applying the function `humanAge` to the resultant `Cat`.

Sometimes it makes more sense to use normal function application, like the above: `humanAge (getCatFromHouse h)` and other times it makes more sense to use function composition like this: `humanAge . getCatFromHouse`, but they mean the same thing. We’ll see more of `(.)` later.

## 14.5. Importing a Module 🔗

Now we’ll see a function from the `Data.List` module called `find` that can be used to get a particular item from a List. A module is a kind of named package of additional functions and types that other programmers have written. So, the `Data.List` module contains lots of good things to do with lists, and it needs to be imported in our file at the top. We’re “aliasing” it (or locally renaming it) to `L` by using the `as` keyword. The `qualified` keyword makes sure when it imports all the function names, it doesn’t load them directly into our local namespace. That way, if we already have things named the same thing as the module we’re importing, there won’t be any conflicts.

``````
-- don't forget, this goes
-- at the top of the file
import qualified Data.List as L
``````

## 14.6. Maybe An Answer 🔗

Let’s look at the type signature for the `find` function, noticing that we’ve qualified the function as being in the `L` aliased namespace by putting `L.find` instead of just `find`:

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

L.find :: Foldable t => (a -> Bool) -> t a -> Maybe a
``````

We can see this function takes two arguments; firstly a function of type `a -> Bool`, and secondly a value of type `Foldable t => t a`. This function then returns another wrapper type. This one is called `Maybe`, and it is wrapping the same type that our `Foldable t => t` is wrappering.

What does this function do, though? Well, it takes that function of `a -> Bool` and applies it to each of the items in the `Foldable t => t a`. If it can’t find any that return `True`, it returns the `Nothing` value, which comes from the `Maybe a` type. If it does find any that return `True`, it returns the first one, wrapped in the `Just` value constructor from the `Maybe a` type.

Here’s an example:

``````
names = ["Harry", "Larry", "Barry"]

result1 = L.find isHarry names
where isHarry name = name == "Harry"
-- result1 will be:
-- Just "Harry"

result2 = L.find isJake names
where isJake name = name == "Jake"
-- result2 will be:
-- Nothing
``````

So we can easily see when it finds a value because `True` was returned by the finding function (also called the predicate, remember?), it returns it wrapped it in `Just`, and when it doesn’t, it returns `Nothing`.

## 14.7. A Little Finding & Sorting 🔗

Let’s put this to work on a function that can find the oldest cat in a list of houses:

``````
findOldestCat :: [House] -> Maybe Cat
findOldestCat []     = Nothing
findOldestCat houses = Just oldestCat
where
oldestCat
= getCatFromHouse houseWithOldestCat
houseWithOldestCat
housesSortedByCatAge
= L.sortBy catAgeComparer houses
catAgeComparer (House _ (Cat _ _ age1))
(House _ (Cat _ _ age2))
= compare age2 age1
``````

This function might look insane at first, but it’s just layers on layers, and we’re going to slowly pull the layers apart together. It’ll be fun, let’s start.

Let’s go from the bottom up. `catAgeComparer` is a function that takes two houses and compares the ages of the cats contained within. It does this by pattern matching the ages out of the cats, and the cats out of each house all at once (its type is `House -> House -> Ordering`).

An `Ordering` is a built-in sum data type which has values of `LT`, `EQ` and `GT` which stand for less than, equal to and greater than respectively. `Ordering` values are used by sorting functions in Haskell.

The `sortBy :: (a -> a -> Ordering) -> [a] -> [a]` function from `Data.List` takes a function whose type is `(a -> a -> Ordering)` to sort its second argument: a list. That fits the type of `catAgeComparer`, which is why we’re using `sortBy` in our definition of `housesSortedByCatAge` in the line above that. Put another way, the `sortBy` function takes a comparing function (that is, one that returns an `Ordering`), and a list, and returns that list sorted by using the comparing function on adjacent elements.

Because we want to sort oldest to youngest, our application of the compare function in `catAgeComparer` has `age2` first. If `age1` was first, it’d sort youngest to oldest.

Next, we have `houseWithOldestCat` which takes the `housesSortedByCatAge` value obtained by sorting the houses, and picks off the first one with the `head` function. It’s only safe to use the `head` function when we can be absolutely sure there is at least one item in the list we’re applying it to. Otherwise it will cause your program to crash (crashing is a term that means the program unexpectedly stopped working). We’re sure that there is at least one item in the list we’re applying `head` to because we have a clause that matches on the empty list and returns `Nothing`.

Finally, `oldestCat` is obtained by applying `getCatFromHouse` to `houseWithOldestCat`, which will obviously just get the cat out of the house.

## 14.8. More About Maybe 🔗

Now we can talk some more about the `Maybe Cat` type that you can see in the `findOldestCat` function’s type signature.

Maybe is a type that takes another type to make types with (this is called a type constructor). That means you can have values of type `Maybe Int`, `Maybe Cat`, `Maybe House`, or `Maybe` any other concrete type you like.

It’s a sort of wrapper for other types, and it’s what we use in Haskell when we want to make a type’s value optional.

In our case, we can’t be 100% sure if the list we pass to `findOldestCat` will contain something. If it is empty, then we obviously can’t pass a `Cat` back at all. The way `Maybe` values work is there’s a value called `Nothing` which represents “no value” of the wrapped type, and there’s a value called “`Just a`” which represents any other value of our wrapped type. Take a look at the following values and their type signatures:

``````
Just 5 :: Num a => Maybe a
Just "Heya" :: Maybe String
Just (Cat "YOOBEY" Sphynx 8) :: Maybe Cat
Nothing :: Maybe Cat
Nothing :: Maybe Integer
Nothing :: Maybe a
``````

You might be surprised to know that `Nothing :: Maybe Cat` can’t be compared to `Nothing :: Maybe Integer`. This is because `Cat` is a different type than `Integer` and you can’t compare differently typed values (unless they’re polymorphic values — that is, values whose types have type variables like `Nothing :: Maybe a`, or `5 :: Num a => a`).

So, `Nothing :: Maybe Cat` means “there are no cats”, and `Just (Cat "YOOBEY" Sphynx 8)` means “a value of the optional-`Cat` type that has a `Cat` in it). This is different than the values whose type is `Cat`, because a value of the type `Cat` must be a `Cat` as defined by the type - it can’t be empty at all.

This is a very nice property for a programming language to have. If there is a value whose type is `Integer`, you can be sure it won’t have anything other than exactly that in it, which makes reading and reasoning about programs much much easier.

However, every positive side has a negative side, too, and the negative side of this is that it makes working with empty things slightly more complicated than if there were just a general value that means an empty thing. We definitely think the complexity is worth it, though, because these optional types are some of the biggest sources of errors in programming languages that don’t have this feature of “typed optionality”.

## 14.9. The Final Program 🔗

We’ve added a `main` function and two additional helper functions:

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

data Cat = Cat Name CatBreed Age
type Name = String
data CatBreed =
Siamese | Persian | Bengal | Sphynx
| Burmese | Birman | RussianBlue
| NorwegianForest | CornishRex | MaineCoon
type Age = Integer

data House = House HouseNumber Cat
type HouseNumber = Int

street :: [House]
street =
[ House 1 (Cat "George" Siamese 10)
, House 2 (Cat "Mr Bigglesworth" Persian 5)
, House 3 (Cat "Mr Tinkles" Birman 1)
, House 4 (Cat "Puddy" Burmese 3)
, House 5 (Cat "Tiger" Bengal 7)
, House 6 (Cat "The Ninja" RussianBlue 12)
, House 7 (Cat "Mr Tinklestein"
NorwegianForest
8)
, House 8 (Cat "Plain Cat" MaineCoon 9)
, House 9 (Cat "Shnooby" Sphynx 7)
, House 10 (Cat "Crazy Ears Sam"
CornishRex
3)
]

humanAge :: Cat -> Age
humanAge (Cat _ _ catAge)
| catAge <= 0 = 0
| catAge == 1 = 15
| catAge == 2 = 25
| otherwise   = 25 + (catAge - 2) * 4

getCatFromHouse :: House -> Cat
getCatFromHouse (House _ c) = c

getHumanAgeOfCatFromHouse :: House -> Age
getHumanAgeOfCatFromHouse =
humanAge . getCatFromHouse

findOldestCat :: [House] -> Maybe Cat
findOldestCat []     = Nothing
findOldestCat houses = maybeOldestCat
where
maybeOldestCat
= case findOldestCatHouse houses of
Just house ->
Just (getCatFromHouse house)
Nothing ->
Nothing

findOldestCatHouse :: [House] -> Maybe House
findOldestCatHouse houses =
if length housesSortedByCatAge > 0
else Nothing
where housesSortedByCatAge
= L.sortBy catAgeComparer houses
catAgeComparer (House _ (Cat _ _ age1))
(House _ (Cat _ _ age2))
= compare age2 age1

getCatName :: Cat -> String
getCatName (Cat name _ _) = name

getHouseNumber :: House -> String
getHouseNumber (House number _) = show number

main :: IO ()
main = putStrLn oldest
where
oldest =
case findOldestCatHouse street of
Nothing ->
"There is no oldest cat!"
Just house ->
"The oldest cat is "
++ getCatName (getCatFromHouse house)
++ ", is "
++ show (getHumanAgeOfCatFromHouse house)
++ " equivalent human years old"
++ " and it lives in Number "
++ getHouseNumber house
``````

Phew! We’ve covered a lot of code in this chapter.

The two helper functions `getCatName` and `getHouseNumber` use pattern matching to grab out the name of a cat and the number of a house (and make sure they’re a string by using the `show` function).

The `main` function uses a definition called `oldest` which uses a `case` expression on the application of `findOldestCatHouse` to `street`, which returns a value of type `Maybe House`. The `case` expression is used to match on either the `Nothing` value to report an error, or the `Just` value, in which case it takes the house out of the `Just` value constructor with pattern matching and creates a nice descriptive sentence about the oldest cat, its age in human equivalent years, and where it lives.

## 14.10. Homework 🔗

Your homework is to write a definition for a name and value whose type is `String`, and a program that prints that `String` using `putStrLn`. Make sure you can do it from memory without looking it up, and write out the types for all definitions in your program.

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