I have this type, basically a Kleisli arrow:
{-# language DeriveFunctor #-}
data Plan m i o = Plan (i -> m o) deriving Functor
instance (Monad m) => Applicative (Plan m i) where
pure x = Plan (\_ -> pure x)
Plan f <*> Plan x = Plan (\i -> f i <*> x i)
Since it has an Applicative
instance, I turn on ApplicativeDo
and try to build a value using do-notation:
{-# language ApplicativeDo #-}
myplan :: Plan IO () ()
myplan = do
pure ()
pure ()
It doesn't work:
No instance for (Monad (Plan IO ())) arising from a do statement
Is there a way to make it work? I'm using GHC 8.0.1.
After searching for ApplicativeDo
-related tickets in the GHC Trac, it appears that is is a known problem:
https://ghc.haskell.org/trac/ghc/ticket/10892
https://ghc.haskell.org/trac/ghc/ticket/12666
Explicitly discarding the result is a workaround:
do
_ <- pure ()
pure ()
ApplicativeDo
does not mean that do
expressions will always be desugared in terms of an applicative functor, but only if it makes sense to do so. Here, it does not. If you have a do
expression like
do
x <- someAction
y <- someAction
return (x + y)
note that the order doesn't really matter, so you could desugar this to
pure (+) <*> someAction <*> someAction
instead of
someAction >>= (\x -> someAction >>= (\y -> return (x + y))
However, the expression
do
pure ()
pure ()
doesn't have any way of being expressed using pure
and <*>
alone. It is not equivalent to pure () <*> pure ()
, because the first value wraps ()
, not a function. Since there is no valid way to desugar this using only an Applicative
instance, the compiler looks for, and fails to find, a Monad
instance to allow pure () >> pure ()
.
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