场景:我有一个解释器,它从 AST 自下而上构建值。某些节点带有权限——额外的布尔表达式。权限失败应该传播,但如果 AST 中的上述节点带有权限,则成功可以恢复计算并停止错误传播。
起初我认为Error MyError MyValue
monad 就足够了:其中一个成员MyError
could be ,如果第二次检查成功PermError
,我可以使用它catchError
来恢复。PermError
但是,MyValue
当我到达处理程序时,它已经消失了。我想最终可能会有一种方法让 PermError 携带一个MyValue
字段,以便处理程序可以恢复它,但它可能会很丑陋,并且在每一步检查异常都会破坏异常发生的概念。
我正在尝试考虑另一种抽象。基本上我必须返回一个数据类型Either AllErrorsExceptPermError (Maybe PermError, MyValue)
或更简单(Maybe AllErrors, MyValue)
(其他错误是不可恢复的并且非常适合错误单子)并且我正在寻找可以让我免于处理元组的东西,因为似乎有一个常见的模式操作是如何链接的。我的haskell知识只到此为止。在这种情况下,你将如何使用 haskell 来发挥你的优势?
当我写这篇文章时,我想到了一个想法(SO 是一个花哨的橡皮鸭):一个在内部处理类型 (a, b) 的 Monad(并最终在 monadic 计算终止时返回它,必须有某种runMyMonad
),但让我尽可能直接使用类型 b。就像是
data T = Pass | Fail | Nothing
instance Monad (T , b) where
return v = (Nothing, v)
(Pass, v) >>= g = let (r', v') = g v in (if r' == Fail then Fail else Pass, v')
(Fail, v) >>= g = let (r', v') = g v in (if r' == Pass then Pass else Fail, v')
(Nothing, _) >>= g = error "This should not have been propagated, all chains should start with Pass or Fail"
错误已被简化为 T,并且该instance
行可能有语法错误,但您应该明白了。这有意义吗?