(r ->) applicative functor

<$> is just another name for fmap and its definition for (->) r is (.) (the composition operator):

intance Functor ((->) r) where
  fmap f g = f . g

You can basically work out the implementation for <*> just by looking at the types:

instance Applicative ((->) r) where
  (<*>) :: (r -> a -> b) -> (r -> a) -> (r -> b)
  f <*> g = \x -> f x (g x)

You have a function from r to a to b and a function from r to a. You want a funtion from r to b as a result. First thing you know is you return a function:

\x ->

Now you want to apply f since it is the only item which may return a b:

\x -> f _ _

Now the arguments for f are of type r and a. r is simply x (since it alrady is of type r and you can get an a by applying g to x:

\x -> f x (g x)

Aaand you're done. Here's a link to the implementation in Haskell's Prelude.


Consider the type signature of <*>:

(<*>) :: Applicative f => f (a -> b) -> f a -> f b

Compare this to the type signature for ordinary function application, $:

($) :: (a -> b) -> a -> b

Notice that they are extremely similar! Indeed, the <*> operator effectively generalizes application so that it can be overloaded based on the types involved. This is easy to see when using the simplest Applicative, Identity:

ghci> Identity (+) <*> Identity 1 <*> Identity 2
Identity 3

This can also be seen with slightly more complicated applicative functors, such as Maybe:

ghci> Just (+) <*> Just 1 <*> Just 2
Just 3
ghci> Just (+) <*> Nothing <*> Just 2
Nothing

For (->) r, the Applicative instance performs a sort of function composition, which produces a new function that accepts a sort of “context” and threads it to all of the values to produce the function and its arguments:

ghci> ((\_ -> (+)) <*> (+ 3) <*> (* 100)) 5
508

In the above example, I have only used <*>, so I’ve explicitly written out the first argument as ignoring its argument and always producing (+). However, Applicative typeclass also includes the pure function, which has the same purpose of “lifting” a pure value into an applicative functor:

ghci> (pure (+) <*> (+ 3) <*> (* 100)) 5
508

In practice, though, you will rarely see pure x <*> y because it is precisely equivalent to x <$> y by the Applicative laws, since <$> is just an infix synonym for fmap. Therefore, we have the common idiom:

ghci> ((+) <$> (+ 3) <*> (* 100)) 5
508

More generally, if you see any expression that looks like this:

f <$> a <*> b

…you can read it more or less like the ordinary function application f a b, except in the context of a particular Applicative instance’s idioms. In fact, an original formulation of Applicative proposed the idea of “idiom brackets”, which would add the following as syntactic sugar for the above expression:

(| f a b |)

However, Haskellers seem to be satisfied enough with the infix operators that the benefits of adding the additional syntax has not been deemed worth the cost, so <$> and <*> remain necessary.


As a Haskell newbie myself, i'll try to explain the best way i can

The <$> operator is the same as mapping a function on to another function.

When you do this:

(+) <$> (+3)

You are basically doing this:

fmap (+) (+3)

The above will call the Functor implementation of (->) r which is the following:

fmap f g = (\x -> f (g x))

So the result of fmap (+) (+3) is (\x -> (+) (x + 3))

Note that the result of this expression has a type of a -> (a -> a)

Which is an applicative! That is why you can pass the result of (+) <$> (+3) to the <*> operator!

Why is it an applicative you might ask? Lets look the at the <*> definition:

f (a -> b) -> f a -> f b 

Notice that the first argument matches our returned function definition a -> (a -> a)

Now if we look at the <*> operator implementation, it looks like this:

f <*> g = (\x -> f x (g x))

So when we put all those pieces together, we get this:

(+) <$> (+3) <*> (+5)
(\x -> (+) (x + 3)) <*> (+5)
(\y -> (\x -> (+) (x + 3)) y (y + 5))
(\y -> (+) (y + 3) (y + 5))