# From Functor to Applicative 林子篆 Originally published at dannypsnl.github.io ・2 min read

Last time we introduce Functor, a Functor is a container which provide a function can help another function operating the Functor. This function has a name fmap in Haskell. Therefore, a function take a type a as parameter(a -> b) can be lifted by fmap to handle M a, if M provided a fmap. For example, Maybe is a Functor, (+1) has the type Int -> Int, fmap (+1) (Just 10) get a result: Just 11.

### Limitation of Functor

Oh, Functor seems so powerful, but programming is simple, life is hard! In the real world, a common situation is there has many M have to handle. For example:

replicateMaybe :: Maybe Int -> Maybe a -> Maybe [a]
replicateMaybe (Just len) (Just a) = Just $replicate n a replicateMaybe _ Nothing = Nothing replicateMaybe Nothing _ = Nothing  Can see that we fall back to pattern matching, line 3 and 4 exclude no input. We can make it easier by extract out this pattern: liftMaybe2 :: (a -> b -> c) -> Maybe a -> Maybe b -> Maybe c liftMaybe2 f (Just a) (Just b) = Just$ f a b
liftMaybe2 _ _ _ = Nothing


Now liftMaybe2 repliacte a b can work just as expected. Sounds great? How about lift a -> b -> c -> d to M a -> M b -> M c -> M d. How about make a lift to another M, e.g. List? liftList? It seems like boilerplate code, right?

Now we have two problems:

1. liftMaybe_n problem, how to handle liftMaybe for all n.
2. liftM problem, how to handle lift for different M.

Indeed, let's dig into fmap again. Every function with type a -> b become M a -> M b, therefore, a -> b -> c would be M a -> M (b -> c). The key point is how to make M (b -> c) applied b.

applyMaybe :: Maybe (a -> b) -> Maybe a -> Maybe b
applyMaybe (Just f) (Just a) = Just $f a applyMaybe _ _ = Nothing  Now take a look at how magic happened: sum :: Int -> Int -> Int -> Int sum a b c = a + b + c (fmap sum$ Just 1) applyMaybe Just 2 applyMaybe Just 3
-- Just 6


We solve liftMaybe_n problem! The only problem is it only works for Maybe, to solve the problem, it's the time of class.

### Applicative can help!

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


<*> is the general version of applyMaybe. pure could raise a variable into the calculation in Applicative, we also call this minimum context.

#### Special helper <$> <$> has definition as below:

(<$>) :: Functor f => (a -> b) -> f a -> f b (<$>) = fmap


It just an alias of fmap to help infix syntax:

(+) <$> Just 1 <*> Just 2 -- Just 3 replicate <$> Just 3 <*> Just 'x'
-- Just "xxx"
replicate <\$> [1, 2, 3] <*> ['x', 'y', 'z']
-- ["x", "y", "z", "xx", "yy", "zz", "xxx", "yyy", "zzz"]


### Conclusion   