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.
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With