Lift to fix the *inside* of a monad transformer stack

吃可爱长大的小学妹 提交于 2019-12-03 21:34:17

问题


Suppose I have an IO Int wrapped in a StateT MyState, then I have a value of State MyState Int which I want to use in the stacked monad. How do I lift it in this inner sense? I already know to use lift or liftIO if I get something compatible with the inside that I just need to lift to the outside monad, but now I have the opposite problem: the value is already in the outer monad but not the inner one.

For instance:

checkSame :: State MyState a -> IO a -> StateT MyState IO Bool
checkSame sim real = do
  rres <- liftIO real
  sres <- ??? sim 
  return $ rres == sres

Do I have to 'get' the state, shove it through runState by hand and box it all up again, or is there some generic way to do this?

BTW, that sim parameter is a whole bunch of stateful functions that have nothing to do with IO, so I'm a bit reluctant to make them all return StateT MyState IO a if I can avoid it.


回答1:


You have two options:

  1. Find a monad morphism. This is often a matter of finding the right library; in this case hoist and generalize together should get you where you need to go.
  2. Make your State action more polymorphic. This is the commonly used one, and the recommended one; it amounts to pre-applying the morphism from part 1, but has a lot of machinery put in place already in the mtl library to make it easy. The idea here is that if you write your State action just in terms of get, put, and modify, then instead of the type State s a, you can give it the type:

    MonadState s m => m a
    

    Then later, at the call site, you can choose whatever monad is appropriate for this, including both State s a and StateT s IO a. Moreover, since it specializes to the type State s a, you can be sure it doesn't do any IO or anything like that that State s a itself couldn't do, so you get the same behavioral guarantees.



来源:https://stackoverflow.com/questions/27200132/lift-to-fix-the-inside-of-a-monad-transformer-stack

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!