Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Which applicative functor is used for passing shared parameters?

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.

like image 621
ondra Avatar asked Jan 06 '12 18:01

ondra


1 Answers

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.

like image 128
Carl Avatar answered Sep 19 '22 14:09

Carl