简体   繁体   中英

Is it possible to implement MaybeT with Applicative only?

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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM