I've been using the Haxl
monad (described here: http://www.reddit.com/r/haskell/comments/1le4y5/the_haxl_project_at_facebook_slides_from_my_talk), which has the interesting feature that <*>
for its Applicative instance isn't the same as ap
from Control.Monad. This is a key feature that allows it to do concurrent computations without blocking. For example, if hf
and ha
are long computations, then
let hf :: Haxl (a -> b) = ...
ha :: Haxl a = ...
in do
f <- hf
a <- ha
return (f a)
will do them sequentially, while
hf <*> ha
will do them in parallel and then combine the results.
I would like to be able to run computations in MaybeT Haxl
, but the problem is that the Applicative instance for MaybeT m
in the transformers package uses monadic bind:
instance (Functor m, Monad m) => Applicative (MaybeT m) where
pure = return
(<*>) = ap
Where ap = liftM2 id
is from Control.Monad
. This makes
let hmf :: MaybeT Haxl (a -> b) = ...
hma :: MaybeT Haxl a = ...
in hmf <*> hma
run sequentially. It seems like a better instance would be more like
instance (Applicative m) => Applicative (MaybeT m) where
pure = MaybeT . pure . Just
MaybeT f <*> MaybeT x = MaybeT $ (<*>) <$> f <*> x
(Here, (<*>)
on the right-hand side is for the Maybe
monad, while the non-parenthesized <*>
on the right-hand side is for m
.) Note that the context is different -- the above instance assumes only Applicative m
, while the instance in transformers assumes Functor m, Monad m
.
My main question is practical: what should I do about this? Should I roll my own MaybeT
monad transformer? Is there some way to get around the "Duplicate instance declarations" complaint that ghc gives me if I try to write the above?
I'd also like to know: is the current setup a design flaw in the transformers package? If not, why not?
Monad
transformers, thus its implementation.Applicative
"transformers" have much nicer structure. – J. Abrahamson<*>
is better, in some significant way, thanap
. It seems to me thatMaybeT
is in the wrong here. – dfeuerApplicative (MaybeT m)
definition. currentlyApplicative
isn't a superclass ofMonad
, so you might break lots of packages. Also I see surprisingly many Foo is instance of Monad but not of Applicative warnings still. Would suggest to write your ownMaybeT
for now - or maybe make a PR totransformers
?. – phadej(<*>)
syntax as convenient and pretty. Once AMP lands this will be even stronger, but it'll also be pretty easy to switch out this definition with the Pplicative only one. – J. Abrahamson