5

关于 Haskell 中的递归方案,我最喜欢的事情之一是广义态射(gcata等),它允许使用 monad 转换器库来交叉(co-)monadic 计算与递归。例如,如这篇精彩的博客文章中所述。

但是,我遇到了一个问题;为了能够使用这些函数,我们需要 (co-)monads 是 (co-)sequentiable。考虑一个类型签名gana

gana : Monad m => (forall z . m (f z) -> f (m z)) -> (a -> f (m a)) -> a -> b

第一个参数本质上说m必须有一个sequence运算符。

不幸的是,我发现在实践中,有些单子不是可分配的。例如:

  • 表示数据库事务的 monad。中止时,事务可以回滚;如果已排序,则只能回滚到已排序的点。
  • 一个并发单子,表示资源上的锁或原子计算。排序后,锁会暂时丢失。

在这种情况下,仍然可以编写一个专门的递归方案来交错单子执行;但是你失去了使用单子变压器融合它的能力。即,如果你想组合这样的非分配单子,它们不能使用变压器与 f-(co) 代数中的单子/共单子进行融合。具体来说,我不能使用 monad 转换器将DBTransactionmonad 与 apomorphism ( ExceptT/EitherT) 结合起来;我需要从头开始编写自定义递归方案。

我的问题是是否有人有解决此限制的建议。

4

0 回答 0