# Why Applicative?

### Christian Gill ・4 min read

100 Days Of FP (10 Part Series)

When learning about the different type classes in Haskell the one I struggled the most with was, by far, Applicative.

### Functor

Functor is, at least to some extent, straightforward. We take any *unary* functions and make them work on some (functor) context.

```
fmap :: Functor f => (a -> b) -> f a -> f b
-- or the infix version
(<$>) :: Functor a => (a -> b) -> f a -> f b
```

Say we have an increment function that works on `Int`

s.

```
inc :: Int -> Int
```

```
λ> inc 1
2
```

By using `fmap`

we can map any functor that contains an `Int`

.

```
λ> fmap inc [1, 2, 3]
[2, 3, 4]
λ> fmap inc (Just 1)
Just 2
λ> fmap inc (Right 1)
Right 2
```

That becomes very clear when we align `fmap`

with the function application operator.

*By the way, we'll use the infix version from now*.

### Applicative

In the case of applicative it's not clear. Or at least it took longer to click for me.

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

Comparing with `($)`

doesn't really help. Why would I want to also have the function in the context?

```
($) :: (a -> b) -> a -> b
(<*>) :: Applicative a => f (a -> b) -> f a -> f b
```

We said functors allow to apply a *unary* function in a context. But what happens if I want to apply a function with a higher arity?

```
add :: Int -> Int -> Int
add <$> (Just 1) -- ??
```

What does the repl says? 🦊

```
λ> :t add <$> (Just 1)
add <$> (Just 1) :: Maybe (Int -> Int)
```

`Maybe (Int -> Int)`

? Yes, we saw that already in the `(<*>)`

signature.

```
add <$> (Just 1) <*> (Just 2) -- Just 3
```

Let's dissect that 🔍

```
-- refresh these ones first :)
(<$>) :: Functor a => (a -> b) -> f a -> f b
(<*>) :: Applicative a => f (a -> b) -> f a -> f b
-- With Maybe applied (using TypeApplications extension)
(<$>) @Maybe :: (a -> b) -> Maybe a -> Maybe b
add :: Int -> Int -> Int
-- With Int applied in place of 'a'
(<$>) @Maybe @Int :: (Int -> b) -> Maybe Int -> Maybe b
-- With (Int -> Int) applied in place of 'b'
(<$>) @Maybe @Int @(Int -> Int)
-- (a -> b) -> Maybe a -> Maybe b
:: (Int -> Int -> Int) -> Maybe Int -> Maybe (Int -> Int)
add <$> (Just 1) :: Maybe (Int -> Int)
```

Here we see the first interesting thing. Since our `add`

function takes two arguments (or to be more accurate one at a time). But we only provide one (the `Int`

from `Maybe Int`

), so it gets partially applied and returns a function (`Int -> Int`

). So `b`

is `Int -> Int`

.

```
-- a -> b
add :: Int -> (Int -> Int)
```

*Note that parens aren't actually needed since the arrow ( ->) is right associative.*

That was the first part of the expression. We are missing the applicative.

```
(<*>) @Maybe :: Maybe (c -> d) -> Maybe c -> Maybe d
-- With Int in place of 'c'
(<*>) @Maybe @Int :: Maybe (Int -> b) -> Maybe Int -> Maybe b
-- And also Int in place of 'd'
(<*>) @Maybe @Int @Int
:: Maybe (Int -> Int) -> Maybe Int -> Maybe Int
```

*Et voilà*

```
add :: Int -> Int -> Int
add <$> (Just 1) :: Maybe (Int -> Int)
add <$> (Just 1) <*> (Just 2) :: Maybe Int
```

**Functor**: apply *unary* functions in a context.

**Applicative**: apply *n-ary* functions in a context.

*This is referred as lift in Haskell.*

And the whole point of applying functions in such contexts is the semantics associated with them. It might be for validation, optional values (without `null`

😏), lists or trees of items, running IO actions, parsers.

When the context is Maybe:

```
λ> add <$> (Just 1) <*> (Just 2)
Just 3
λ> add <$> Nothing <*> (Just 2)
Nothing
λ> add <$> (Just 1) <*> Nothing
Nothing
λ> add <$> Nothing <*> Nothing
Nothing
```

When the context is Either:

```
λ> add <$> (Right 1) <*> (Right 2)
Right 3
λ> add <$> (Left "err 1") <*> (Right 2)
Left "err 1"
λ> add <$> (Right 1) <*> (Left "err 2")
Left "err 2"
λ> add <$> (Left "err 1") <*> (Left "err 2")
Left "err 1"
```

When the context is List:

```
λ> add <$> [1, 2, 3] <*> [1, 2, 3]
[2,3,4,3,4,5,4,5,6]
λ> (,) <$> [1, 2, 3] <*> [1, 2, 3]
[(1,1),(1,2),(1,3),(2,1),(2,2),(2,3),(3,1),(3,2),(3,3)]
```

☝️ *More on that on the next one*.

### Conclusion

When learning functional programming all these type classes might seem scary. Developing a basic intuition of their purpose and usages is a big part of the process of getting comfortable using (and understanding) them.

I know there are more implications around Functor and Applicative that I have yet to discover. But as any learning process, it takes time. I'm sure more things will become clear and start sink in as I keep going.

But that's all for today.

Happy and safe coding 🎉

100 Days Of FP (10 Part Series)

Very good article. There are a lot of issues in many publications about Applicative, they show it with relation with Monad, or get into A from M.

Showing this just as a Functor with additional powers, possibility to apply n-unary functions is much much better approach.

Tnx.

Thanks Maciej!

There's indeed more to Applicative (as well as Functors, Monads, et al). Specially if one gets in the theoretical side. Which is useful. But as a developer all I want is to be able to have the necessary intuition to use it in practice, right?

I'm currently learning about applicatives as well, so it's cool to see this. I particularly like the insight that applicatives are about applying n-ary functions in a context, the same way functors are about applying unary functions in a context. Very helpful - thanks!

Glad it was useful :)

I really enjoy the whole series, keep it up, it's so much fun to read and learn a bit more all the time ;)

It mostly me sharing what I'm learning, so I'm really glad it helps somebody else :)

It's just in the right time, I started to learn Haskell with Advent of Code 2019, and I really like it and these posts are very useful extra sources for getting more and more in a clean format ;)

Glad to hear! 🎉

Make sure to check out A Type of Programming by @k0001. I started recently with it and is a pleasure to read.

## A Type of Programming

## Renzo Carbonara ・ Apr 24 '19 ・ 1 min read

Thank you For the feedback. will address this :)