haskell - 提升以固定单子(monad)变压器堆栈的“内部”

标签 haskell monad-transformers lifting

假设我有一个 IO Int 包裹在 StateT MyState 中,那么我有一个我想要使用的 State MyState Int 值在堆叠的单子(monad)中。我如何在这种内在的意义上提升它?我已经知道使用 liftliftIO 如果我得到与内部兼容的东西,我只需要提升到外部 monad,但现在我遇到了相反的问题: value 已经在外部 monad 中,但不在内部 monad 中。

例如:

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它。

最佳答案

您有两个选择:

  1. 找到单子(monad)态射。这通常是找到合适的库的问题;在这种情况下hoistgeneralize在一起应该可以带您到达您需要去的地方。
  2. 使您的 State 操作更加多态。这是常用的,也是推荐的;它相当于预先应用第 1 部分中的态射,但在 mtl 库中已经放置了很多机制以使其变得简单。这里的想法是,如果您仅根据 getputmodify 编写 State 操作,然后,您可以为其指定类型,而不是 State s a 类型:

    MonadState s m => m a
    

    然后,在调用站点,您可以选择适合于此的任何 monad,包括 State s aStateT s IO a。此外,由于它专门针对 State s a 类型,因此您可以确定它不会执行任何 IOState s a 类似的操作本身做不到,所以你得到相同的行为保证。

关于haskell - 提升以固定单子(monad)变压器堆栈的“内部”,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27200132/

相关文章:

scala - 是否可以在 Scala 中实现 liftM2?

c++ - 以函数方式组合谓词

haskell - 自动将 Either 提升到 exceptT

haskell - 计算期间在环境中隐式携带 STRef

scala - 如何在 scalaz 7 中使用变压器在 monad 堆栈之间进行转换

haskell - 在 Haskell 中使用 foldl 遍历树

haskell - 输入安全的相等元组大小。

haskell - 不将类型识别为转换器堆栈中 monad 的关联类型

Haskell 读/写二进制文件完整工作示例

Haskell:找不到模块 `Data.List.Split'