提起以修复单体变压器堆叠的*内部* [英] Lift to fix the *inside* of a monad transformer stack

查看:96
本文介绍了提起以修复单体变压器堆叠的*内部*的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

假设我有一个包含在 StateT MyState 中的 IO Int ,那么我的值为 State MyState Int ,我想在堆叠monad中使用它。如何从内在意义上解除它?我已经知道要使用 lift liftIO ,如果我得到与内部兼容的东西,我只需要提升到外部单子,但现在我有相反的问题:价值已经在外部单子,而不是内部单子。



例如:

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

我必须'取得'状态,通过runState手动推动它并再次将其全部覆盖,或者是否有一些通用的方法来做到这一点?

顺便说一句,该sim参数是一大堆有状态函数与IO无关,所以我有点不情愿让它们都返回 StateT MyState IO a ,如果我可以避免的话。

$ b $你有两种选择:


  1. 找到单态射线。这通常是找到合适的图书馆的问题;在这种情况下,提升概括一起应该让你去你需要去的地方。
  2. 让你的状态动作更具多态性。这是常用的和推荐的;它相当于预先应用第1部分的态射,但是已经在 mtl 库中放置了大量机制,以方便使用。这里的想法是,如果你只用 get 来编写你的 State 操作,put 修改,然后而不是类型 State sa ,您可以给它键入:

      MonadState sm => ma 

    然后,在呼叫站点,您可以选择适合的monad,包括两个 State sa StateT s IO a 。此外,由于它专注于 State sa 类型,因此您可以确定它不会执行任何 IO 或任何其他任何操作就像 State sa 本身无法做到的一样,所以你可以得到相同的行为保证。 $ b

    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.

    解决方案

    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.

    这篇关于提起以修复单体变压器堆叠的*内部*的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆