Question

I think I kind of understand how applicative functors work in Haskell and I'm using them for basic datatypes (Maybe, Either...). However, I found this question with the following example:

withPool pool = bracket (takeConn pool) (putConn pool)

can be rewritten in applicative style:

withPool = bracket <$> takeConn <*> putConn

I was surprised it compiled and indeed it works as expected, but could somebody tell me which Applicative Functor is used for this and how is it defined?

Update: I think I figured out how it works, but I have no idea where is it defined.

Was it helpful?

Solution

Unify f = (a ->) in the type signatures:

fmap :: (b -> c) -> (a -> b) -> (a -> c)
pure :: b -> (a -> b)
(<*>) :: (a -> b -> c) -> (a -> b) -> (a -> c)

The only reason the declarations are syntactically different, ((->) a) vs (a ->), is that you aren't allowed to take sections at the type level. So you end up with these, after chasing types:

instance Functor ((->) a) where
    fmap = (.)

instance Applicative ((->) a) where
    pure = const
    f <*> g = \x -> f x $ g x

I'm pretty sure the Functor instance is in Data.Functor, and the Applicative instance is in Control.Applicative. The Monad instance for ((->) a) is the only one in a strange spot, in Control.Monad.Instances, instead of Control.Monad. At least if I recall correctly.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top