Running `:i Applicative`

in ghci yields the following:

```
class Functor f => Applicative (f :: * -> *) where
pure :: a -> f a
(<*>) :: f (a -> b) -> f a -> f b
GHC.Base.liftA2 :: (a -> b -> c) -> f a -> f b -> f c
(*>) :: f a -> f b -> f b
(<*) :: f a -> f b -> f a
```

It also lists available instances of the *Applicative* type class:

```
instance Applicative (Either e) -- Defined in ‘Data.Either’
instance Applicative [] -- Defined in ‘GHC.Base’
instance Applicative Maybe -- Defined in ‘GHC.Base’
instance Applicative IO -- Defined in ‘GHC.Base’
instance Applicative ((->) a) -- Defined in ‘GHC.Base’
instance Monoid a => Applicative ((,) a) -- Defined in ‘GHC.Base’
```

## Concrete type signatures

To understand similarities and differences between various instances of the *Applicative* type class we will take a look at the type signatures of the `pure`

, `<*>`

and `liftA2`

functions for `List`

, `Maybe`

and `Either`

types:

```
-- Generic
pure :: a -> f a
-- List
pure :: a -> [a]
-- Maybe
pure :: a -> Maybe a
-- Either
pure :: a -> Either l a
```

```
-- Generic
(<*>) :: f (a -> b) -> f a -> f b
-- List
(<*>) :: [(a -> b)] -> [a] -> [b]
-- Maybe
(<*>) :: Maybe (a -> b) -> Maybe a -> Maybe b
-- Either
(<*>) :: Either l (a -> b) -> Either l a -> Either l b
```

```
-- Generic
liftA2 :: (a -> b -> c) -> f a -> f b -> f c
-- List
liftA2 :: (a -> b -> c) -> [a] -> [b] -> [c]
-- Maybe
liftA2 :: (a -> b -> c) -> Maybe a -> Maybe b -> Maybe c
-- Either
liftA2 :: (a -> b -> c) -> Either l a -> Either l b -> Either l c
```

## Using `pure`

with different types

`pure`

lifts a value to a given type. The type can be inferred or specified with a type annotation like in the examples below:

```
-- List
(pure 2 :: [Integer]) == [2]
```

```
-- Maybe
(pure 2 :: Maybe Integer) == Just 2
```

```
-- Either
(pure 2 :: Either a Integer) == Right 2
```

Interactive Examples:

## Using `<*>`

with different types

In order to use `<*>`

we need to define some functions we want to work with. After they are defined we will apply them to some instances of the *Applicative* type class:

```
addOne :: Num a => a -> a
addOne a = a + 1
addTwo :: Num a => a -> a
addTwo a = a + 2
```

```
-- List
[ ] <*> [ ] == [ ]
[ ] <*> [2] == [ ]
[addOne] <*> [ ] == [ ]
[addOne] <*> [2] == [3]
[addOne, addTwo] <*> [ ] == [ ]
[addOne, addTwo] <*> [2] == [3, 4]
[addOne, addTwo] <*> [2, 3] == [3, 4, 4, 5]
```

```
-- Maybe
Nothing <*> Nothing == Nothing
Nothing <*> Just 2 == Nothing
Just addOne <*> Nothing == Nothing
Just addOne <*> Just 2 == Just 3
```

```
-- Either
Left addOne <*> Left 2 == Left addOne
Left addOne <*> Right 2 == Left addOne
Right addOne <*> Left 2 == Left 2
Right addOne <*> Right 2 == Right 3
```

Interactive Examples:

## Using `liftA2`

with different types

To use `liftA2`

we also need to define a function. The function will accept two parameters and return a single value. After the function is defined we will apply it to some instances of the *Applicative* type class:

```
add :: Num a => a -> a -> a
add a b = a + b
```

```
-- List
import Control.Applicative (liftA2)
liftA2 add [ ] [ ] == []
liftA2 add [1] [ ] == []
liftA2 add [1] [2] == [3]
liftA2 add [1,2] [2] == [3,4]
liftA2 add [1,2] [2,3] == [3,4,4,5]
```

```
-- Maybe
import Control.Applicative (liftA2)
liftA2 add (Nothing) (Nothing) == Nothing
liftA2 add (Nothing) (Just 2) == Nothing
liftA2 add (Just 1) (Nothing) == Nothing
liftA2 add (Just 1) (Just 2) == Just 3
```

```
-- Either
import Control.Applicative (liftA2)
liftA2 add (Left 1) (Left 2) == Left 1
liftA2 add (Left 1) (Right 2) == Left 1
liftA2 add (Right 1) (Left 2) == Left 2
liftA2 add (Right 1) (Right 2) == Right 3
```

Interactive Examples:

Applicatives are not scary either. They are pretty useful as you can see above. Let me know on twitter if you have any comments - @maciejsmolinski.

In the next post you will learn about Monads.