Applicative functors are more powerful than Functors but not as powerful as monads. They provide a way to partially apply a function inside an Applicative context to parameters also inside the same context.

Confused? Well hopefully after this article you won’t be.

As we saw earlier, a Functor is just a Haskell typeclass with the
single required `fmap`

function.

class Functor f wherefmap :: (a -> b) -> f a -> f b

We can apply a function from `a -> b`

to a value wrapped inside of a functor
context.

Now what if we want to apply a function to multiple arguments that are all
wrapped inside of a context? Such as summing two numbers wrapped in a `Maybe`

.

(Just 1) + (Just 2) -- ?

If we apply `fmap`

to `Just 1`

with the `(+)`

function we get back another
function wrapped in the `Maybe`

context.

ghci> :t (+) <$> Just 1(+) <$> Just 1 :: Num a => Maybe (a -> a)

But now we are stuck. We need to apply a function inside of the Maybe context to a number inside the Maybe context.

This is where Applicatives come in!

They allow us to take a function which operates on normal unwrapped values, and apply it to parameters which are all wrapped in a context.

The typeclass definition requires all Applicatives to be Functors (meaning they
all implement the `fmap`

function).

class (Functor f) => Applicative f wherepure :: a -> f a(<*>) :: f (a -> b) -> f a -> f b

Additionally, an Applicative must implement the `pure`

and `(<*>)`

functions.

`pure`

just takes a normal unwrapped value and wraps it into an Applicative
context.

`(<*>)`

takes a function wrapped in an Applicative context and a parameter also
wrapped. It then unwraps both, applies `a`

to the function, and wraps the result
back up.

Lets see how it is implemented for the `Maybe`

type.

instance Applicative Maybe wherepure x = Just x(Just f) <*> (Just x) = Just (f x)_ <*> _ = Nothing

If either Maybe types are `Nothing`

then `Nothing`

is returned. Otherwise, each
value is unwrapped (via pattern matching), the function is applied to the
contents of second Maybe, and the result is wrapped back up as a Maybe.

Since all functions in Haskell are curried, we can partially apply a function of
`n`

arguments to `n`

parameters wrapped in the Applicative context.

Using our above example, summing two numbers wrapped in a Maybe would look like this

ghci> (+) <$> Just 1 <*> Just 2Just 3

We first use `<$>`

to partially apply `+`

to `Just 1`

. Functor stuff. But then
we use `<*>`

to take the wrapped function and apply it to the wrapped parameter.

Alternatively we can use the `pure`

function to wrap `(+)`

inside of an
Applicative.

ghci> pure (+) <*> Just 1 <*> Just 2Just 3

What happens if one of the parameters is `Nothing`

?

ghci> (+) <$> Just 1 <*> NothingNothing

This is awesome! We don’t have to worry about checking whether or not our
parameters are valid. The `(<*>)`

function does that for us under the hood.