抬起以固定monad变压器堆栈的*inside*

Adr*_*May 3 haskell monad-transformers lifting

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

例如:

checkSame :: State MyState a -> IO a -> StateT MyState IO Bool
checkSame sim real = do
  rres <- liftIO real
  sres <- ??? sim 
  return $ rres == sres
Run Code Online (Sandbox Code Playgroud)

我是否必须"获取"状态,手动将其推入runState并将其全部重新装箱,或者是否有一些通用的方法来执行此操作?

顺便说一句,那个sim参数是一大堆与IO无关的有状态函数,所以StateT MyState IO a如果我能避免它,我有点不愿意让它们全部返回.

Dan*_*ner 7

您有两种选择:

  1. 找一个monad态射.这通常是找到合适的图书馆的问题; 在这种情况下,提升概括在一起应该让你到达你需要去的地方.
  2. 让你的State行动更具多态性.这是常用的,推荐的; 它相当于预先应用第1部分中的态射,但在mtl图书馆中已经有很多机器可以使它变得容易.这里的想法是,如果你写你的State行动只是来讲get,putmodify,然后,而不是类型State s a,你可以给它的类型:

    MonadState s m => m a
    
    Run Code Online (Sandbox Code Playgroud)

    然后,在呼叫站点,您可以选择适合此的monad,包括State s aStateT s IO a.此外,由于它专门针对类型State s a,你可以确定它不会做任何IO或类似的事情State s a本身无法做到,所以你得到相同的行为保证.