开发者

Why the boilerplates when writing new Monad Transformers

开发者 https://www.devze.com 2023-01-29 14:30 出处:网络
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

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:

  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.
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号