Christian Kjær

In a recent thread on /r/haskell about how to motivate the AMP proposal in teaching, I read a comment that finally helped me understand the purpose of `Functor`

s, `Applicative`

s and `Monad`

s.

For the reader that hasn't followed this debacle, the AMP proposal is basically about making `Applicative`

a superclass of `Monad`

. That this hasn't been so is often considered one of the historical errors Haskell carries around, since a `Monad`

is always an `Applicative`

.

The hierachy of `Functor`

, `Applicative`

and `Monad`

is thus changed to,

1
2 -- ...
3
4
5 -- ...
6
7
8 -- ...

which makes more sense than the arbitrary split before (i.e. `Monad`

was just "on its own").

The concerns surrounding this change has mostly been about beginner-friendliness, since a `Monad`

now needs an instance of both `Applicative`

and `Functor`

.

There are various other considerations, which the interested reader can find out more about on the GHC 7.10 migration page or the Haskell wiki entry about AMP.

I'm mostly going to paraphrase /u/ForTheFunctionGod's comment (which you can find here), while trying to expand a bit on it with my own understanding.

One can naturally extend the intuition of a `Functor`

to an `Applicative`

and from there to a `Monad`

.

**An explanation of the first two might go as follows:**

Let's say I have a list of numbers and want to add

`2`

to each of these numbers. You can write`fmap (+2) [1..10]`

(using`Functor`

).But what if I had two lists of numbers and wanted to add each number from the first list to each number from the second list? With

`Applicative`

you can do just that - it's like`fmap`

only it can take multiple arguments. You can write`(+) <$> [1,5,10] <*> [11..13]`

.^{1}

**From here, one can motivate Monad by asking:**

What if I wanted to abort midway through - say, if I encountered a problem? You can then write:

^{1}

1 add xs ys = do
2 x <- xs
3 if x < 0 then []
4 else do
5 y <- ys
6 if y < 0 then []
7 else return (x+y)

Thus we have the natural hierachy:

`Functor`

: apply a function to a container.`Applicative`

: apply a multi-argument function to multiple containers.`Monad`

: like`Applicative`

but I can decide what to do next after each step.

While the above may help a bit in the *"why?"*, there is still the question of how to use them. I won't go into much detail since there exists a wealth of information on this topic already (you can quickly google them), but just give some brief examples of what happens when using them.

** Functor is the simplest**, and can be thought of as a much more general

`map`

. Wherever you use `map`

you can always replace it with `fmap`

, but not the other way around.```
> fmap (*2) [1..10]
[2,4,6,8,10,12,14,16,18,20]
```

`fmap`

simply takes every element of the list and applies the function to it.

** Applicative on the other hand** is a bit more tricky to understand. The best starting point is probably to show where

`fmap`

is not enough.Imagine we want to apply the function `*`

(multiplication) to a list, we could try `fmap (*) [1..3]`

but that would give us a bunch of partially applied functions back, like `[(*1), (*2), (*3)]`

.

Now, what can we do with this? We can for example map a value onto the list of partially applied functions, which would look something like this using `fmap`

,

```
> let a = fmap (*) [1..3]
> fmap (\f -> f 9) a
[9,18,27]
```

which can be seen as applying a function that takes a function as argument an applies `9`

to that function, to every function in the list `a`

. The real problem comes when we want to apply a `Functor`

function to `Functor`

values, but I won't get into much detail on that (you can read more here).

Luckily, instead of writing the above, we can use `<*>`

which is a part of `Applicative`

. We can instead write,

```
> fmap (*) [1..3] <*> [9]
[9,18,27]
```

Note that the reason we put `9`

inside a context (here a list), is because `Applicative`

expects everything to be a `Functor`

. Since the first part is so common, `Control.Applicative`

actually exports `<$>`

, so we can do the following instead, replacing `fmap`

,

```
> (*) <$> [1..3] <*> [9]
[9,18,27]
```

Admittedly, it's a bit more interesting when we want to apply the multiple functions to multiple arguments, as such,

```
> (*) <$> [1,5,10] <*> [11..13]
[11,12,13,55,60,65,110,120,130]
> (*) <$> Just 3 <*> Just 5
```

or perhaps inside contexts, such as `Maybe`

,

```
> (*) <$> Just 3 <*> Just 5
Just 15
```

but I won't go into more detail about that, since that isn't the purpose of this post.

** Monad is the last**, but perhaps most tricky. I'll try to be as brief as possible though. Too see the

`Maybe`

monad used with `do`

notation. It will not explain `Monad`

usage in general, but should be enough to get the gist that For example (note that I use ; instead of linebreaks because we are executing in the GHCi REPL),

```
> do Just 6; Nothing; Just 9
Nothing
```

You may be aware that a `do`

block returns the last line executed in it - so why did it here return `Nothing`

when the last line was `Just 9`

? That is because on each step the bind function `>>=`

(or `=<<`

for the other direction) is applied. The `Maybe`

`Monad`

defines that if it encounters a `Nothing`

then every subsequent actions also return a `Nothing`

.

To understand this better, let's take a look at the `Maybe`

instance,

1
2 return x = Just x
3 Nothing >>= f = Nothing
4 Just x >>= f = f x
5 fail _ = Nothing

Notably here is the line that says `Nothing >>= f = Nothing`

. It throws away whatever future action it gets and just returns `Nothing`

. This is in contrast to `Just x >>= f = f x`

which can be seen as unpacking `x`

from `Just x`

and then applying the future action, `f`

, to that `x`

.

Hopefully this should have helped understand the difference of `Functor`

, `Applicative`

and `Monad`

a bit, and how they work together. To understand these concepts more in depth, I recommend reading a bit up on them, and especially for `Monad`

, try reading about the `Writer`

and `State`

`Monad`

s, how they are used and how they are implemented. One resource for that is the chapter on a few more monads in LYAH.

If you are confused about *"What exactly is a Functor, is it a class or interface or whatever?"*, then I gave my take on it here. Other than that, I encourage that you read a bit on Type Class'.

Finally, I can deeply recommend the book Haskell Programming - from first principle. It is still in development as of this date, but already features 700 pages of quality content. Simply the best Haskell book I have ever read (or, I'm still reading it as of writing).

https://www.reddit.com/r/haskell/comments/3tpom7/amp_how_do_you_motivate_this_in_teaching/cx8an8b