Question

This section http://book.realworldhaskell.org/read/monad-transformers.html#id659032 from the book Real World Haskell suggests that when writing a new Monad Transformer, we have to derive instances for MonadState, MonadIO, etc. manually.

But I tried the following and it compiled. Why is it not done in the library?

Say I have the MaybeT monad transformers:

newtype MaybeT m a = MaybeT {
    runMaybeT :: m (Maybe a)
}

instance Monad m => Monad (MaybeT m) where -- blah blah

instance MonadTrans MaybeT where
    lift = MaybeT . (liftM Just)

Then once we know that t is a MonadTrans and m is a Monad, why can't everything else be automatically derived like this?

instance (MonadTrans t, Monad (t m), MonadIO m) => MonadIO (t m) where
    liftIO = lift . liftIO

instance (MonadTrans t, Monad (t m), MonadState s m) => MonadState s (t m) where
    get = lift get
    put = lift . put

Does the author mean we have to do this manually for each new MonadTrans or I get him wrong?

Thank you very much :)

Was it helpful?

Solution

The reason why they don't do this is very simple:

  1. First, it would break a lot of old code if they would add this, because you need some stuff like UndecidableInstances to let GHC decide between the automatic and the manually defined instance. This would be very cumbersome.
  2. What, if you want to define an instance different from the above, maybe for performance reasons or to do some hack? I think this little boilerplate is preferable over the inability / higher cost (because of the trickery to tell GHC which instance you want) of defining customized instances, if this instance would be builtin.
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top