# Applicative Functor for beginners

*This article presumes beginner level knowledge of Haskell programming language on part of the reader. To get the most out of this article some knowledge of basic Haskell syntax, basic data types like Maybe and Either, and Functor typeclass will be highly beneficial.*

## What this post covers?

After reading this post you’ll have a basic understanding of Applicative Functors. You’ll also see some relatable real-life problems where Applicative Functors can come in handy and yield an elegant solution.

## Applicative Functor

In an earlier article I explained about Functors. A quick refresher is that a Functor is a container or a context whose value(s) could be mapped over with a function to produce a new Functor. This is done using the `fmap`

function. Haskell defines the following typeclass for Functors.

```
class Functor f where
fmap :: (a -> b) -> f a -> f b
```

Applicative Functor is a Functor that has a few more tricks up its sleeve. List, Maybe, Either all are Applicative Functors as we’ll discover later. First let’s see the extra functions that it supports.

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

`(Functor f) =>`

just means that any Applicative must also be a Functor; it is a constraint. The first function we have is `pure :: a -> f a`

. This is a simple function that takes any value and returns an Applicative Functor that wraps the value. You can think of it as providing a `Maybe`

, it wraps the value in a `Just`

. And for an `Either`

it wraps the value in a `Right`

. I hope there are no surprises here.

```
-- ghci (Haskell shell)
λ> pure "fpunfold" :: Maybe String
Just "fpunfold"
λ> pure "fpunfold" :: [String]
["fpunfold"]
λ> pure "fpunfold" :: Either String String
Right "fpunfold"
```

The second function Applicative Functor supports is `(<*>) :: f (a -> b) -> f a -> f b`

. As the type signature suggests, `<*>`

takes an Applicative (short for Applicative Functor) that contains a function of type `a -> b`

and applies it to a value inside another Applicative `f a`

, while merging the contexts of the two Applicatives. Hmm.. who in their right mind would wrap a function inside a container like Applicative?. This might look funky at first but trust me it’ll make much more sense later when you see it in action with some examples. But before that let’s see how `Maybe`

is an Applicative.

## Maybe type as an Applicative

`Maybe`

has the following implementation for Applicative typeclass (actual implementation in Haskell source is slightly different but does the exact same thing).

```
instance Applicative Maybe where
pure x = Just x
Just f <*> Just x = Just (f x)
_ <*> _ = Nothing
```

`pure`

function just wraps the value in `Just`

. For `<*>`

it makes sense that we can perform function application only when both the function and the value are available inside the two `Maybe`

s provided. If either isn’t available then the result is `Nothing`

. Let’s confirm that this does what we expect.

```
-- ghci
λ> Just (\x -> x + 1) <*> Just 3
Just 4
λ> Just (\x -> x + 1) <*> Nothing
Nothing
λ> Nothing <*> Just 3
Nothing
λ> Nothing <*> Nothing
Nothing
```

Phew! after all this theory I can finally show you some example of when this is useful. Recall that functions in Haskell are https://fpunfold.com/2020/05/09/why-haskell-for-functional-programming/#currying by default meaning that passing one argument to a multi-argument function returns another function that takes one less parameter. You can think of this as partially applying functions. So, when you do `(+) 2`

it creates a new function that takes one integer and adds 2 to it. What do you think would happen if we do `Just (+) <*> Just 2`

? Let’s analyze its type signature in ghci using `:t`

command.

```
// ghci
λ> :t Just (+) <*> Just 2
Just (+) <*> Just 2 :: Num a => Maybe (a -> a)
```

We see that the signature of the function returned by `<*>`

is `Num a => Maybe (a -> a)`

, which is a function wrapped inside a new `Maybe`

Applicative Functor. Now we can pass it to `<*>`

again with a fresh argument value!

```
λ> Just (+) <*> Just 2 <*> Just 4
Just 6
```

We now have a result value wrapped in `Maybe`

since our function `(+)`

has been passed all the parameters it requires (2 and 4 in the example above). What does this mean? It means that we can take any arbitrary function, wrap it in a `Maybe`

(called “lifting to Applicative”) and apply it successively to arguments wrapped in `Maybe`

. If at any stage we see an argument that is `Nothing`

, the result will automatically be `Nothing`

. This simplifies and standardizes error handling!

```
λ> Just (+) <*> Just 2 <*> Just 4
Just 6
λ> Just (+) <*> Nothing <*> Just 4
Nothing
λ> Just (+) <*> Just 2 <*> Nothing
Nothing
```

Now let’s see a more relatable example. Suppose we want to parse parameters passed in a query string (a string containing key-value pairs). Say we want to parse the query string `firstName=fp&lastName=unfold&age=0&email=contact@fpunfold.com`

to a data type representing a Person. Our function should account for missing information in the encoded string and should fail gracefully in such cases. Let’s define our `Person`

data type and write the type signature for our function.

```
-- applicative.hs
data Person = Pers {
_firstName :: String
, _lastName :: String
, _age :: Int
, _email :: String
} deriving Show
parseMaybe :: String -> Maybe Person
```

Our data type `Person`

contains four required fields that we want to parse from a query string. Function `parseMaybe`

is our parsing function that tries to parse the passed query string and returns a `Just Person`

if it was successful, and returns `Nothing`

on any failure like insufficient information in the query string. To do that, we’ll first extract all (key, value) tuples from the query string using a `decode`

function as shown below. We are using `splitOn`

function from module Data.List.Split here. You can download the package using `cabal install split`

command if you don’t have it available.

```
-- applicative.hs
import Data.List.Split (splitOn)
decode :: String -> [(String,String)]
decode encoded =
fmap toTup . filter validTup . fmap (splitOn "=") . splitOn "&" $ encoded
where
toTup [x,y] = (x,y)
validTup xs = length xs == 2
```

`decode`

function first splits the encoded string on “&” character. Each part in the result is now expected to be a key-value pair separated by “=” character. So, we split each part on “=” character (mapping with `splitOn "="`

) and filter out ones that do not contain exactly two elements after the split as those parts are invalid. Then, we just map all two-element lists (key-value pairs) to tuples. Let’s test the function in ghci.

```
// ghci
λ> :l applicative.hs
[1 of 1] Compiling Main ( applicative.hs, interpreted )
Ok, one module loaded.
λ> decode "firstName=fp&lastName=unfold&age=0&email=contact@fpunfold.com"
[("firstName","fp"),("lastName","unfold"),("age","0"),("email","contact@fpunfold.com")]
λ> decode "firstName=fp&this=part=is=invalid"
[("firstName","fp")]
λ> decode ""
[]
```

Now we create a `parsem :: [(String,String)] -> Maybe Person`

function that’ll try to create a `Person`

from the key-value pairs. It uses Applicative Functor functions of `Maybe`

to elegantly handle any errors.

```
-- applicative.hs
parsem :: [(String,String)] -> Maybe Person
parsem kvs = pure Pers
<*> lookup "firstName" kvs
<*> lookup "lastName" kvs
<*> fmap read (lookup "age" kvs)
<*> lookup "email" kvs
```

And that’s all! Our `parsem`

function looks for all the required fields in the passed key-value pairs using `lookup :: Eq k => k -> [(k, v)] -> Maybe v`

function that returns the value corresponding to the passed key if found or `Nothing`

otherwise. To handle any missing information automatically we make use of `<*>`

function. First, we lift the `Pers`

Data Constructor (which is just a function that creates a `Person`

) using `pure`

(which is `Just`

for `Maybe`

Applicative) and then we partially apply it on arguments wrapped in `Maybe`

using `<*>`

. If at any point an optional argument is `Nothing`

, `<*>`

returns `Nothing`

and then the whole chain evaluates to `Nothing`

. For age of the person we first lookup age in string format using `lookup`

function and then convert it to an `Int`

by mapping it with `read`

function. Now, our final `parseMaybe :: String -> Maybe Person`

function is just a composition of `parsem`

and `decode`

.

```
-- applicative.hs
parseMaybe :: String -> Maybe Person
parseMaybe = parsem . decode
```

```
// ghci
λ> parseMaybe "firstName=fp&lastName=unfold&age=0&email=contact@fpunfold.com"
Just (Pers {_firstName = "fp", _lastName = "unfold", _age = 0, _email = "contact@fpunfold.com"})
λ> parseMaybe "firstName=fp&lastName=unfold&age=0" -- missing email
Nothing
λ> parseMaybe "firstName=fp&&email=contact@fpunfold.com" -- missing lastName and age
Nothing
```

## Either as an Applicative

Similar to `Maybe`

, `Either l`

is also an Applicative Functor as shown below.

```
instance Applicative (Either e) where
pure = Right
Left e <*> _ = Left e
Right f <*> r = fmap f r
```

Implementation is similar to `Maybe`

. `<*>`

performs function application only if both sides are `Right`

. Otherwise it returns `Left`

value from first or second parameter in that order.

Our `parsem`

function works well but it doesn’t tell us much about failures. What if we want to know what field was missing? Is there another type that’s like `Maybe`

but slightly more informative? It’s the `Either`

type! We can use `Either String Person`

instead of `Maybe Person`

so that we can return some error in string format if something fails. And since `Either String`

is an Applicative our code remains almost the same.

```
-- applicative.hs
eitherMaybe :: l -> Maybe r -> Either l r
eitherMaybe e Nothing = Left e
eitherMaybe _ (Just x) = Right x
parsee :: [(String,String)] -> Either String Person
parsee m = pure Pers
<*> eitherMaybe "firstName absent" (lookup "firstName" m)
<*> eitherMaybe "lastName absent" (lookup "lastName" m)
<*> eitherMaybe "age absent" (fmap read . lookup "age" $ m)
<*> eitherMaybe "email absent" (lookup "email" m)
```

Since `lookup`

function returns a `Maybe`

we first need an easy way to convert it to an `Either`

. We define a simple `eitherMaybe`

function to handle this. It takes an error value and a `Maybe`

. For `Just x`

it wraps the value in a `Right`

and for `Nothing`

it returns the passed error value wrapped in a `Left`

. Next is our new parsing function `parsee`

. It remains almost identical in structure to our `parsem`

function. The only difference is that we convert the `Maybe`

results of `lookup`

function into `Either`

and provide an informative error message if the lookup failed. The usage of Applicative’s `<*>`

function remains the same. Instead of working on `Maybe`

s it works on `Either`

s this time.

Let’s also define a `parseEither :: String -> Either String Person`

function like we defined `parseMaybe`

before.

```
-- applicative.hs
parseEither :: String -> Either String Person
parseEither = parsee . decode
```

Let’s give it a go in ghci.

```
// ghci
λ> :l applicative.hs
[1 of 1] Compiling Main ( applicative.hs, interpreted )
Ok, one module loaded.
λ> parseEither "firstName=fp&lastName=unfold&age=0&email=contact@fpunfold.com"
Right (Pers {_firstName = "fp", _lastName = "unfold", _age = 0, _email = "contact@fpunfold.com"})
λ> parseEither "firstName=fp&lastName=unfold&age=0" -- missing email
Left "email absent"
λ> parseEither "firstName=fp&&email=contact@fpunfold.com" -- missing lastName and age
Left "lastName absent"
```

Isn’t this great?

## Summary

We saw what Applicative Functors are and how they can be useful in providing elegant solutions to some every day problems. In fact, Haskell language has some powerful and brilliant parsing tools based on something called Parser Combinators which in turn are based on Applicative functors! I will cover Parser Combinator in separate posts. We also haven’t seen how other Applicatives such as Lists behave and what are some more interesting properties of Applicatives. All that will be future articles as well! I hope you learned a thing or two from this post and that your time here was well spent. :)