After revisiting my MaybeT
excercise I got warning that I should also have Applicative
instance. I tried to implement it but got stuck as I cannot find way to apply mx
to mf
with Applicative m
. Do I need Monad m
?
newtype MaybeT m x = MaybeT { runMaybeT :: m (Maybe x) }
instance Functor m => Functor (MaybeT m) where
fmap f m = MaybeT $ fmap z $ runMaybeT m where
z (Just x) = Just $ f x
z Nothing = Nothing
instance Applicative m => Applicative (MaybeT m)
I think you do need Monad
. Basically, if you have
f :: MaybeT m (a -> b)
x :: MaybeT m a
and if, when evaluating f <*> x
, running the unwrapped f
in m
returns a Nothing
, then the action for x
shouldn't run at all - but you cannot achieve that without using that m
is a Monad
, since Applicative
combinators intuitively always run all the subactions.
By the way, the simplest way to generate an Applicative
just to satisfy the new AMP requirement, is to use
import Control.Monad (ap)
instance Applicative ... where
pure = return
(<*>) = ap
For Functor
you can either use fmap = liftM
, or the DeriveFunctor
extension.
MaybeT
could be defined as
newtype Compose f g x = Composed (f (g x))
newtype MaybeT m x = MaybeT (Compose m Maybe x)
and applicatives do compose . Hence you can write an applicative instance for MaybeT
like this:
instance Applicative m => Applicative (MaybeT m) where
pure = MaybeT . pure . Just
f <*> x = MaybeT $ (<*>) <$> runMaybeT f <*> runMaybeT x
EDIT
As @Ørjan Johansen and @dfeuer explain, this is not a true instance for the MaybeT
transformer, since the definition of (<*>)
violates the f <*> x == ap fx
law. Here is an example:
test :: MaybeT IO ()
test = MaybeT (return Nothing) <*> MaybeT (putStrLn "test" >> return Nothing)
main = runMaybeT test
This code prints test
with my wrong definition and doesn't print anything with the right one.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.