Avoiding lift with monad transformers

前端 未结 2 1840
一个人的身影
一个人的身影 2021-01-29 22:36

I have a problem to which a stack of monad transformers (or even one monad transformer) over IO. Everything is good, except that using lift before every action is t

2条回答
  •  轻奢々
    轻奢々 (楼主)
    2021-01-29 23:10

    For all the standard mtl monads, you don't need lift at all. get, put, ask, tell — they all work in any monad with the right transformer somewhere in the stack. The missing piece is IO, and even there liftIO lifts an arbitrary IO action down an arbitrary number of layers.

    This is done with typeclasses for each "effect" on offer: for example, MonadState provides get and put. If you want to create your own newtype wrapper around a transformer stack, you can do deriving (..., MonadState MyState, ...) with the GeneralizedNewtypeDeriving extension, or roll your own instance:

    instance MonadState MyState MyMonad where
      get = MyMonad get
      put s = MyMonad (put s)
    

    You can use this to selectively expose or hide components of your combined transformer, by defining some instances and not others.

    (You can easily extend this approach to all-new monadic effects you define yourself, by defining your own typeclass and providing boilerplate instances for the standard transformers, but all-new monads are rare; most of the time, you'll get by simply composing the standard set offered by mtl.)

提交回复
热议问题