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.