# Why Applicative?

*Originally posted on dev.to/gillchristian*.

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 f => (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.

```
($) :: (a -> b) -> a -> b
(<$>) :: Functor f => (a -> b) -> f a -> f b
inc $ 1 -- 2
inc <$> [1] -- [2]
inc <$> (Just 1) -- Just 2
```

*fmap is just function application inside a context.*

*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 f => 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 -> b) -> f a -> f b
(<*>) :: Applicative f => 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** 🎉