# Functors, Applicatives, And Monads In Pictures (In Elm)

## Elm Version

This is a translation of Functors, Applicatives, And Monads In Pictures from Haskell into Elm. I left the Haskell examples as reference.
I don’t want to take any merit for writing this, I only went through the fun exercise of translating the code snippets in Elm.
If you enjoy this post be sure to say thanks to the author of the original version: Aditya Bhargava, @_egonschiele on Twitter.
This is the list of operators and function mentioned in the article:
(+) Addition
(*) Multiplication
(//) Integer division
(%) Modulo operation
(<|) Backward function application
(|>) Forward function application
(<<) Function composition
(>>) Function composition
Maybe.Maybe
Maybe.map
Maybe.map2
Maybe.andThen
List.map
List.concatMap
With parenthesis operator can be used without the infix notation like`2 + 3 == (+) 2 3`, so `(+)3` return a function with type annotation `number -> number`.
All Elm code example can run inside elm-repl, if you don’t have Elm installed you can use the online version of elm-repl. To write multiline command be sure to add “/” at the end of the line, if not already present.

Here’s a simple value:

And we know how to apply a function to this value:

Simple enough. Lets extend this by saying that any value can be in a context. For now you can think of a context as a box that you can put a value in:

Now when you apply a function to this value, you’ll get different results depending on the context. This is the idea that Functors, Applicatives, Monads, Arrows etc are all based on. The `Maybe` data type defines two related contexts:

`In Haskell:`
``data Maybe a = Nothing | Just a``
`In Elm:`
`type Maybe a = Nothing | Just a`

In a second we’ll see how function application is different when something is a `Just a` versus a `Nothing`. First let's talk about Functors!

### Functors

When a value is wrapped in a context, you can’t apply a normal function to it:

This is where `fmap` comes in. `fmap` is from the street, `fmap` is hip to contexts. `fmap` knows how to apply functions to values that are wrapped in a context. For example, suppose you want to apply `(+3)` to `Just 2`. Use `fmap`:

`In Haskell:`
``> fmap (+3) (Just 2)Just 5``
`In Elm:`
`> Maybe.map ((+)3) (Just 2)Just 5`
`---`
`Elm doesn't have typeclasses (info here and here) so let's use directly Maybe.map. The type signature of Maybe.map is`
`Maybe.map : (a -> b) -> Maybe a -> Maybe b`
`that is a special case of`
`fmap :: (a -> b) -> fa -> fb`
`where f = Maybe`

Bam! `fmap` shows us how it's done! But how does `fmap` know how to apply the function?

### Just what is a Functor, really?

`Functor` is a typeclass. Here's the definition:

A `Functor` is any data type that defines how `fmap` applies to it. Here's how `fmap` works:

So we can do this:

`In Haskell:`
``> fmap (+3) (Just 2)Just 5``
`In Elm:`
`> Maybe.map ((+)3) (Just 2)Just 5`

And `fmap` magically applies this function, because `Maybe` is a Functor. It specifies how `fmap`applies to `Just`s and `Nothing`s:

`In Haskell:`
``instance Functor Maybe where    fmap func (Just val) = Just (func val)    fmap func Nothing = Nothing``
`In Elm:`
`This is how Maybe.map is defined in Elm:`
`map func maybe =    case maybe of      Just val -> Just (func val)      Nothing  -> Nothing`

Here’s what is happening behind the scenes when we write `fmap (+3) (Just 2)`:

So then you’re like, alright `fmap`, please apply `(+3)` to a `Nothing`?

`In Haskell:`
``> fmap (+3) NothingNothing``
`In Elm:`
`> Maybe.map ((+)3) NothingNothing`

Like Morpheus in the Matrix, `fmap` knows just what to do; you start with `Nothing`, and you end up with `Nothing`! `fmap` is zen. Now it makes sense why the `Maybe` data type exists. For example, here's how you work with a database record in a language without `Maybe`:

``post = Post.find_by_id(1)if post  return post.titleelse  return nilend``

But in Haskell:

`In Haskell:`
``fmap (getPostTitle) (findPost 1)``
`In Elm:`
`Maybe.map `getPostTitle (findPost 1)``

If `findPost` returns a post, we will get the title with `getPostTitle`. If it returns `Nothing`, we will return `Nothing`! Pretty neat, huh? `<\$>` is the infix version of `fmap`, so you will often see this instead:

`In Haskell:`
``getPostTitle <\$> (findPost 1)``
`In Elm:`
`Maybe.map `getPostTitle (findPost 1)``
`---`
`infix operators will not be supported in new releases of Elm so let's keep using Maybe.map`

Here’s another example: what happens when you apply a function to a list?

Lists are functors too! Here’s the definition:

`In Haskell:`
``instance Functor [] where    fmap = map``
`In Elm:`
`List.map`

Okay, okay, one last example: what happens when you apply a function to another function?

`In Haskell:`
``fmap (+3) (+1)``
`In Elm:`
`(+)3 << (+)1`
`---`
`In Elm "<<" and ">>" are the infix operators for function composition`

Here’s a function:

Here’s a function applied to another function:

The result is just another function!

`In Haskell:`
``> import Control.Applicative> let foo = fmap (+3) (+2)> foo 1015``
`In Elm:`
`> foo = (+)3 << (+)2> foo 1015`

So functions are Functors too!

`In Haskell:`
``instance Functor ((->) r) where    fmap f g = f . g``
``In Elm:``
`(>>) g f x = f (g x)(<<) f g x = f (g x)`

When you use fmap on a function, you’re just doing function composition!

### Applicatives

Applicatives take it to the next level. With an applicative, our values are wrapped in a context, just like Functors:

But our functions are wrapped in a context too!

Yeah. Let that sink in. Applicatives don’t kid around. `Control.Applicative` defines `<*>`, which knows how to apply a function wrapped in a context to a value wrapped in a context:

i.e:

``In Haskell:``
``Just (+3) <*> Just 2 == Just 5``
`In Elm:`
`Just ((+)3) |> applicative (Just 2) == Just 5`
`---`
`Elm doesn't have <*>. We can achieve the same result defining "applicative" as`
`> applicative maybeValue maybeCallback = \    case maybeCallback of \        Just callback -> case maybeValue of \                Just value -> Just (callback value) \                Nothing -> Nothing \        Nothing -> Nothing`
`or shortly as`
`> applicative = Maybe.map2 (|>)`
`type signature is`
`applicative : Maybe (a -> b) -> Maybe a -> Maybe b`
`while in Haskell`
`(<*>) :: f(a -> b) -> fa -> fb`

Using `<*>` can lead to some interesting situations. For example:

`In Haskell:`
``> [(*2), (+3)] <*> [1, 2, 3][2, 4, 6, 4, 5, 6]``
`In Elm:`
`> [(*)2, (+)3] |> applicativeList [1, 2, 3]`[2, 4, 6, 4, 5, 6]``
`---`
`In this case we need to build a new applicative for the list`
`> applicativeList l fl = \    List.concatMap (\f -> List.map (\i -> f i) l) fl`

Here’s something you can do with Applicatives that you can’t do with Functors. How do you apply a function that takes two arguments to two wrapped values?

`In Haskell:`
``> (+) <\$> (Just 5)Just (+5)> Just (+5) <\$> (Just 4)ERROR ??? WHAT DOES THIS EVEN MEAN WHY IS THE FUNCTION WRAPPED IN A JUST``
`In Elm:`
`> Maybe.map (+) (Just 5)Just ((+)5)> Maybe.map (Just ((+)5)) (Just 4)`
`-- TYPE MISMATCH -----------------------------`
`The 1st argument to function `map` is causing a mismatch.`
`7|   Maybe.map (Just ((+)5)) (Just 4)                ^^^^^^^^^^Function `map` is expecting the 1st argument to be:`
`a -> Maybe (number -> number)`
`But it is:`
`Maybe (number -> number)`
`Hint: It looks like a function needs 1 more argument.`

Applicatives:

`In Haskell:`
``> (+) <\$> (Just 5)Just (+5)> Just (+5) <*> (Just 3)Just 8``
`In Elm:`
`> Maybe.map (+) (Just 5)Just ((+)5)> Just ((+)5) |> applicative (Just 3)Just 8`

`Applicative` pushes `Functor` aside. "Big boys can use functions with any number of arguments," it says. "Armed `<\$>` and `<*>`, I can take any function that expects any number of unwrapped values. Then I pass it all wrapped values, and I get a wrapped value out! AHAHAHAHAH!"

`In Haskell:`
``> (*) <\$> Just 5 <*> Just 3Just 15``
`In Elm:`
`> Maybe.map (*) (Just 5) |> applicative (Just 3)Just 15`

And hey! There’s a function called `liftA2` that does the same thing:

`In Haskell:`
``> liftA2 (*) (Just 5) (Just 3)Just 15``
`In Elm:`
`> Maybe.map2 (*) (Just 5) (Just 3)Just 15`

### Monads

How to learn about Monads:

1. Get a PhD in computer science.
2. Throw it away because you don’t need it for this section!

Monads add a new twist.

Functors apply a function to a wrapped value:

Applicatives apply a wrapped function to a wrapped value:

Monads apply a function that returns a wrapped value to a wrapped value. Monads have a function `>>=` (pronounced "bind") to do this.

Let’s see an example. Good ol’ `Maybe` is a monad:

Suppose `half` is a function that only works on even numbers:

`In Haskell:`
``half x = if even x           then Just (x `div` 2)           else Nothing``
`In Elm:`
`half x = if even x \           then Just (x // 2) \           else Nothing`
`---`
`"even" is not part of the standard library. It can be defined like:`
`even n = n % 2 == 0`

What if we feed it a wrapped value?

We need to use `>>=` to shove our wrapped value into the function. Here's a photo of `>>=`:

Here’s how it works:

``In Haskell:``
``> Just 3 >>= halfNothing> Just 4 >>= halfJust 2> Nothing >>= halfNothing``
`In Elm:`
`> Just 3 |> Maybe.andThen halfNothing> Just 4 |> Maybe.andThen halfJust 2> Nothing |> Maybe.andThen halfNothing`
`---`
`The analogue of ">>=" in Elm, for Maybe, is Maybe.andThen that is defined as:`
`andThen : (a -> Maybe b) -> Maybe a -> Maybe bandThen callback maybeValue =    case maybeValue of        Just value ->            callback value`
`        Nothing ->            Nothing`

What’s happening inside? `Monad` is another typeclass. Here's a partial definition:

``In Haskell:``
``class Monad m where    (>>=) :: m a -> (a -> m b) -> m b``
``In Elm:` `
`andThen : (a -> Maybe b) -> Maybe a -> Maybe b`

Where `>>=` is:

So `Maybe` is a Monad:

``In Haskell:``
``instance Monad Maybe where    Nothing >>= func = Nothing    Just val >>= func  = func val``
`In Elm:`
``andThen func maybe =    case maybe of        Nothing -> Nothing        Just val -> func val``

Here it is in action with a `Just 3`!

And if you pass in a `Nothing` it's even simpler:

You can also chain these calls:

`In Haskell:`
``> Just 20 >>= half >>= half >>= halfNothing``
`In Elm:`
`> Just 20 \    |> Maybe.andThen half \    |> Maybe.andThen half \    |> Maybe.andThen halfNothing`
`---`
`To recap, in Haskell:`
`Functors      (<\$>) ::  (a ->  b) -> fa -> fbApplicatives  (<*>) :: f(a ->  b) -> fa -> fbMondads       (>>=) ::  (a -> fb) -> fa -> fb`
`In Elm, using the Maybe monad as example:`
`Maybe.map     :       (a ->       b) -> Maybe a -> Maybe bapplicative   : Maybe (a ->       b) -> Maybe a -> Maybe bMaybe.andThen :       (a -> Maybe b) -> Maybe a -> Maybe b`
``I rearranged the terms of "(>>=) :: m a -> (a -> m b) -> m b" `to highlight the similarities with Functors and Applicatives and also to be consistent with the type signature of Maybe.andThen. To be composable the terms need to be in the proper position. This is why in Elm we use "|>" to chain andThen.`
`In Haskell:`
``Just 20 >>= half``
`In Elm:`
`Just 20 |> Maybe.andThen half`
`or`
`Maybe.andThen half (Just 20)`

Cool stuff! So now we know that `Maybe` is a `Functor`, an `Applicative`, and a `Monad`.

Now let’s mosey on over to another example: the `IO` monad:

Specifically three functions. `getLine` takes no arguments and gets user input:

`In Haskell:`
``getLine :: IO String``
`In Elm:`
`getTime : Task.Task x Time.Time`
`---`
`Instead "IO String", let's use "Task err ok" in Elm.`
`We will build a different example:`
`Let suppose that we want to get the present time and use it as parameter in a first http request to get a page, and then use the returned page as parameter for a second http request to get a second page.`
`1. get the present time2. get a page using the time as parameter3. get a second page using the first page as parameter`
`So, getLine (in the Haskell example) will be getTime in Elm:`
`getTime = Time.now`
`to run these examples in the elm-repl, remember to run these commands first:`
`import Taskimport Timeimport Http`

`readFile` takes a string (a filename) and returns that file's contents:

`In Haskell:`
``readFile :: FilePath -> IO String``
`In Elm:`
`readFile : a -> Task.Task Http.Error String`
`---`
`For example:`
`readFile time = \    Http.getString ("https://example.com?time=" ++ toString time) \        |> Http.toTask`

`putStrLn` takes a string and prints it:

`In Haskell:`
``putStrLn :: String -> IO ()``
`In Elm:`
`readSecondFile : a -> Task.Task Http.Error String`
`---`
`For example:`
`readSecondFile response = \    Http.getString ("https://example.com?response=" ++ toString response) \        |> Http.toTask`

All three functions take a regular value (or no value) and return a wrapped value. We can chain all of these using `>>=`!

`In Haskell:`
``getLine >>= readFile >>= putStrLn``
`In Elm:`
`getTime \    |> Task.andThen readFile \    |> Task.andThen readSecondFile`

Aw yeah! Front row seats to the monad show!

Haskell also provides us with some syntactical sugar for monads, called `do` notation:

``foo = do    filename <- getLine    contents <- readFile filename    putStrLn contents``

### Conclusion

1. A functor is a data type that implements the `Functor` typeclass.
2. An applicative is a data type that implements the `Applicative` typeclass.
3. A monad is a data type that implements the `Monad` typeclass.
4. A `Maybe` implements all three, so it is a functor, an applicative, and a monad.

What is the difference between the three?

• functors: you apply a function to a wrapped value using `fmap` or `<\$>` (for example: `Maybe.map` in Elm)
• applicatives: you apply a wrapped function to a wrapped value using `<*>` or `liftA` (for example: `Maybe.map2 (|>)` or `Maybe.map2` in Elm)
• monads: you apply a function that returns a wrapped value, to a wrapped value using `>>=` or `liftM` (for example: `Maybe.andThen` in Elm)

So, dear friend (I think we are friends by this point), I think we both agree that monads are easy and a SMART IDEA(tm). Now that you’ve wet your whistle on this guide, why not pull a Mel Gibson and grab the whole bottle. Check out LYAH’s section on Monads. There’s a lot of things I’ve glossed over because Miran does a great job going in-depth with this stuff.

Examples in Ellie: https://ellie-app.com/NZqfGnCyBpa1

This is a translation of Functors, Applicatives, And Monads In Pictures from Haskell into Elm. I left the Haskell examples as reference.
I don’t want to take any merit for writing this, I only went through the fun exercise of translating the code snippets in Elm.
If you enjoy this post be sure to say thanks to the author of the original version: Aditya Bhargava, @_egonschiele on Twitter.