Lecture 20: Monad Transformers

*Exercise 20.1

Compared to the free Functor instance we saw in class, provide a direct implementation:

instance Functor m => Functor (MaybeT m) where ...

*Exercise 20.2

Compared to the free Applicative instance we saw in class, provide a direct implementation:

instance Monad m => Applicative (MaybeT m) where ...

Optional exercises:

Exercise 20.3

The MaybeT m instance of Alternative we saw in class requires that m is in Monad as well as Alternative. Define an alternative instance that forgoes the latter requirement.

instance Monad m => Alternative (MaybeT m) where ...

When finished, compare your implementation to the canonical version.

Exercise 20.4

Consider the types of the monad transformers:

newtype MaybeT m a = MaybeT { runMaybeT :: m (Maybe a) } newtype ListT m a = ListT { runListT :: m [a] } newtype StateT s m a = StateT { runStateT :: s -> m (a, s) } newtype ReaderT r m a = ReaderT { runReaderT :: r -> m a } newtype WriterT w m a = WriterT { runWriterT :: m (a, w) }

When we use MaybeT to add Maybe behavior to another monad, it's curious that the Maybe type goes inside the other monad. Why is the wrapping order m (Maybe a) instead of Maybe (m a) as in the WrapMaybe type below?

newtype WrapMaybe m a = WrapMaybe { runWrapMaybe :: Maybe (m a) }

To answer this question, you might try implementing (>>=) for WrapMaybe. Work from WrapMaybe.hs and attempt to get bind to typecheck.