# Haskell for Elm developers: giving names to stuff (Part 2 - Applicative Functors)

Since the previous post had some measure of success, I decided to continue the series! 🎉

Without much preamble, let’s look at the typeclass definition in Haskell for Applicative Functors:

```
class (Functor f) => Applicative f where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
```

This looks a bit scarier 👻 at the beginning, but do not worry, we will explain every bit at a time.

The first thing we can notice is that the typeclass definition has itself a typeclass constraint! This is new for us, we did not know that could happen (until now), and this is what the `class Functor f =>`

bit means.

**What are the implications of this?** Well, as you might have already guessed, it just means one simple thing: *every* Applicative Functor must be first a *valid Functor*, not a very big surprise, right? 😉

The second thing we can notice is that, contrary to the `Functor`

typeclass declaration that specified only a function to be implemented (`fmap`

), now we have 2 functions every Applicative Functor must have to satisfy the instance: `pure`

, and the mysterious `<*>`

operator, which we will call the TIE fighter operator from now on (because I love the name and yes, I’m a big STAR WARS fan 🤓).

Let’s talk about each of them separately but first, spoiler alert ⚠️, in Elm, some examples of Applicative Functors you use every day are: `List`

, `Maybe`

, `Result`

and `Task`

.

## The `pure`

function

Out of the two needed functions, `pure`

is probably the easiest to explain: it just “lifts” any value `a`

into an Applicative Functor context `f`

.

`pure :: a -> f a`

What are some examples of this in Elm? For example, the `List.singleton`

function!

```
> List.singleton
<function> : a -> List a
```

Okay, what about `Maybe`

?

```
> Just
<function> : a -> Maybe a
```

This might be new for you, but **data constructors are also functions!** 🤯

This means that for `Maybe`

we just have *one* `pure`

function (`Nothing`

is just a value, not a function), and you probably can guess what is the `pure`

implementation for `Result`

:

```
> Ok
<function> : value -> Result error value
```

This example is a little harder to understand, because the `f`

Applicative Functor *structure* is actually `Result error`

, so that this matches:

```
pure :: value -> f value
Ok : value -> Result error value
```

Note that, because of this, the `Err`

contructor/function is *not* a correct implementation, since the Applicative Functor structure is not preserved:

```
> Err
<function> : error -> Result error value
```

You can probably see here that there is no `f a`

structure, so only `Ok`

could be considered the correct implementation of `pure`

for `Result`

.

To keep with the Elm explanations, `Task.succeed`

is the `pure`

equivalent for the `Task`

Applicative Functor:

```
> import Task
> Task.succeed
<function> : a -> Task.Task x a
```

## The TIE fighter operator (`<*>`

)

Now let us begin with the fun part:

`(<*>) :: f (a -> b) -> f a -> f b`

This is an *infix operator* that takes a lifted function `f (a -> b)`

and a lifted value `f a`

and somehow magically *applies* (that’s why sometimes this function is also refered to as `apply`

or just `ap`

) the lifted function to the lifted `a`

to finally return a lifted `b`

value (`f b`

). But by now you should be wondering: **how on Earth is this actually useful!? 🤔**

Well, let’s have a peek at the actual implementation of the `Applicative`

typeclass in `GHC.Base`

:

```
class (Functor f) => Applicative f where
{-# MINIMAL pure, ((<*>) | liftA2) #-}
-- | Lift a value.
pure :: a -> f a
-- | Sequential application.
(<*>) :: f (a -> b) -> f a -> f b
<*>) = liftA2 id
(
-- | Lift a binary function to actions.
-- ==== __Example__
-- >>> liftA2 (,) (Just 3) (Just 5)
-- Just (3,5)
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
= (<*>) (fmap f x) liftA2 f x
```

First thing we notice is that there is a MINIMAL pragma, this tells GHC (the main compiler of Haskell) that the required functions that a type needs to implement in order to have a valid `Applicative`

instance are `pure`

and `<*>`

OR `liftA2`

.

Second thing we can notice, is that `<*>`

and `liftA2`

are almost identical: they are defined in terms of each other! 🤯

So, `liftA2`

is basically:

`= (<*>) (fmap f x) liftA2 f x `

And, the TIE fighter operator is just:

`<*>) = liftA2 id (`

The `id`

function is the silliest function in Haskell: `id :: a -> a`

and in Elm is properly called `identity`

:

```
> identity
<function> : a -> a
```

The fact that these two functions are defined in terms of each other, just means that you need to implement one of them, and you will get the other one for free. But, leaving that behind us, does not the type declaration of `liftA2`

look familiar to us Elm developers? 👀

`liftA2 :: (a -> b -> c) -> f a -> f b -> f c`

Besides, looking at the example code given, can we achieve something similar in Elm?

```
-- ==== __Example__
-- >>> liftA2 (,) (Just 3) (Just 5)
-- Just (3,5)
```

The answer is: yes, we can! 🚀

```
> Maybe.map2 Tuple.pair (Just 3) (Just 5)
Just (3,5) : Maybe ( number, number1 )
```

Remember how I told you on the previous post that infix operators were just superior in Haskell? We are not able to do this `(,)`

in Elm, so we need to resign ourselves to just use `Tuple.pair : a -> b -> ( a, b )`

, which does basically the same.

If we query the Elm REPL for the type of `Maybe.map2`

, we get:

```
> Maybe.map2
<function> : (a -> b -> value) -> Maybe a -> Maybe b -> Maybe value
```

Compare this to the type of `liftA2`

again:

```
liftA2 :: (a -> b -> value) -> f a -> f b -> f c
Maybe.map2 : (a -> b -> value) -> Maybe a -> Maybe b -> Maybe value
```

You guessed it correctly: the `liftA2`

equivalent in Elm are all the `*.map2`

functions we can find!

So, when we said before that `List`

, `Maybe`

, `Result`

and `Task`

were **Applicative Functors in Elm**, is because we have `List.map2`

, `Maybe.map2`

, `Result.map2`

and `Task.map2`

.

This ties in nicely with an excellent article published by Joël Quenneville some time ago, called “Running Out of Maps” (very nice pun btw 😜).

In that post, he explains that if anytime you run out of `mapN`

functions, you can define this simple combinator:

`andMap = Maybe.map2 (|>)`

And if we query again the Elm REPL for the type of `andMap`

we get the following:

```
> andMap = Maybe.map2 (|>)
<function> : Maybe a -> Maybe (a -> value) -> Maybe value
```

Am gonna casually remind you right now about the type declaration of the TIE fighter operator, in case you forgot:

`(<*>) :: f (a -> b) -> f a -> f b`

**What can we draw from all this crazyness?**

We just FOUND THE TIE FIGHTER OPERATOR IN ELM! It is just `flip andMap`

!! 😎

**So why all of this is important again and when the heck am I going to use Applicative Functors (I hear your mind saying 🧠💭)???**

Well, if you have ever used the `Json.Decode.Extra`

package, you might have probably written code like this:

```
decoder : Decoder Document
decoder =
Decode.succeed Document
|> Decode.andMap (Decode.field "id" Decode.string)
|> Decode.andMap (Decode.field "title" Decode.string)
|> Decode.andMap documentTypeDecoder
|> Decode.andMap (Decode.field "ctime" Iso8601.decoder)
|> Decode.andMap (Decode.field "mtime" Iso8601.decoder)
```

The exact same code in Haskell, using our beloved infix operators, would look like this:

```
decoder :: Decoder Document
=
decoder Document
<$> decodeStringField "id"
<*> decodeStringField "title"
<*> documentTypeDecoder
<*> decodeIso8601Field "ctime"
<*> decodeIso8601Field "mtime"
```

This means two things:

- You have been using Applicative Functors all along for a very long time probably without notice! 🥁🥁🥁
- Of course, this also means that Json.Decode.Decoder is also an Applicative Functor!! 👏🏻

## Acknowledgements

Many people has made possible the production of this blogpost, I want to personally thank Robert Pearce for his excellent Hakyll + Nix tutorial, and Domen Kožar, for all his work with Cachix and the Nix ecosystem in general (and for his infinite patience 😇).

I would also like to thank Chris Allen and Julie Moronukie, because together they created the Haskell Book™️, which is still in my opinion **the best possible way to learn Haskell** and it is actually the reason I am today working with Haskell.

Could not be more grateful to all of them! 😍

Enough bad puns for today, hope you learned something new! If you enjoyed this post and would like me to continue the series (*next up would probably be MOOONAAAAAADSSSS 👻🦇🦇🦇*), please share it in your social networks and **follow me on Twitter!** 🙌🏻