Why the boilerplates when writing new Monad Transformers
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 . li开发者_如何学CftIO
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 :)
The reason why they don't do this is very simple:
- 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. - 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.
精彩评论