#
Haskell 笔记：Applicative

原文链接 https://hsfzxjy.github.io/haskell-applicative/

注：以下为加速网络访问所做的原文缓存，经过重新格式化，可能存在格式方面的问题，或偶有遗漏信息，请以原文为准。

## Motivation

`Functor`

solves the problem of mapping regular one-parameter functions into a sub-category, but that's not easy for functions with more than one parameters.

Let's consider a function with two parameters `f :: a -> b -> c`

, which can also read as `a -> (b -> c)`

. Applying `fmap`

on `f`

, we will get `fmap f :: m a -> m (b -> c)`

. There's still some distance from what we want: `f' :: m a -> m b -> m c`

. To get `f'`

, we need a transform from `m (b -> c)`

to `m b -> m c`

. Here we denote it as `<*> :: m （b -> c) -> m b -> m c`

. We will later show that such transform is universal for functions with more parameters.

Now consider a function with three parameters `f :: a -> b -> c -> d`

. We are going to transform it into a wrapped-value version, with the help of `fmap`

and `<*>`

.

```
f :: a -> b -> c -> d
(fmap f) :: m a -> m (b -> (c -> d))
\a_ b_ -> (fmap f a_) <*> b_
:: m a -> m b -> m (c -> d)
\a_ b_ c_ -> ((fmap f a_) <*> b_) <*> c_
:: m a -> m b -> m c -> (m d)
```

Here `\a_ b_ c_ -> ((fmap f a_) <*> b_) <*> c_`

is in the desired type. For most of the time, applying parameters directly is actually what we want, instead of the function itself, so the code could simply be written as `((fmap f a) <*> b) <*> c`

, where `a`

, `b`

and `c`

are wrapped values. Parenthesis could be omitted if precedences are set properly, which leads to a neat and easy-to-read form:

```
f `fmap` a <*> b <*> c
```

In haskell, `fmap`

has an infix name `<$>`

. So finally we get: `f <$> a <*> b <*> c`

.

## Applicative

Haskell pre-defined a type class `Applicative`

, which captures the pattern `<*>`

. Any type that implements `Applicative`

works well with `<$>`

and `<*>`

.

```
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
```

Note that an `Applicative`

is also a `Functor`

. Apart from `<*>`

, there are some other helper functions or operators in `Applicative`

.

`pure`

is equivalent to the default value constructor of `f`

, e.g. `(:[])`

for `List`

or `Just`

for `Maybe`

. This may be handful when lifting an unwrapped value to a wrapped one.

`liftA2`

transforms a binary operator to the corresponding version. The function exists as binary operators would be frequently passed among high-order functions.

`*>`

takes two wrapped parameters and simply returns the second one, which sequence up two wrapped values. This is quite useful for `Applicative`

with action semantics, such as `IO`

. In fact, it's so useful that Haskell introduces a syntax sugar for it, known as the `do-notation`

. Particularly:

```
do
putStrLn "1"
putStrLn "2"
```

is equivalent to

```
putStrLn "1" *> putStrLn "2"
```

`<*`

is similar. Both will be reviewed while studying Monad.