# Haskell 笔记：Applicative

## Motivation

`Functor`

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

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

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

. Applying `fmap`

on `f`

will yield `fmap f :: m a -> m (b -> c)`

. That’s still distant from what we expect: `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-defines a type class `Applicative`

, which captures the pattern of `<*>`

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

Author:hsfzxjy.Link:.License:CC BY-NC-ND 4.0.

All rights reserved by the author.

Commercial use of this post in any form isNOTpermitted.

Non-commercial use of this post should be attributed with this block of text.

## OOPS!

A comment box should be right here...But it was gone due to network issues :-(If you want to leave comments, make sure you have access to disqus.com.