【问题标题】:Accumulating errors using ErrorT使用 ErrorT 累积错误
【发布时间】:2016-11-04 16:45:28
【问题描述】:

是否可以在 ErrorT monad 中累积错误消息?我想累积更多的错误。

【问题讨论】:

  • Either / ExceptT / ErrorT 本质上被设计为短路,所以答案是“否”。但是,如果您想累积多个错误,则应该使用不同的 monad/monad 转换器,在这种情况下可能是 WriterT
  • 用 WriterT 替换 ErrorT 难吗?此时我有“塔:monad(StateT,ErrorT,IO)
  • 从机械难度的意义上说并不难,但从ErrorTWriterT 的语义截然不同的意义上说,这可能是困难的。 ErrorT 的全部意义在于它允许计算失败。如果您想累积多个错误,那么这意味着您可能希望计算继续进行。考虑一下这对你的代码有什么影响——你真的能在失败后继续前进吗?如果答案是“有时”,您可能需要混合使用WriterTExceptT(顺便说一下,不推荐使用ErrorT,改用ExceptT)。
  • 那么“累积不止一个错误”是什么意思?错误的想法是执行立即结束,所以一旦你有一个错误,你就不能再有了。

标签: haskell exception-handling monads either


【解决方案1】:

您可以使用来自 transformersControl.Applicative.LiftErrors Applicative:

ghci> import Control.Applicative
ghci> import Control.Applicative.Lift
ghci> failure ['a'] *> pure () <* failure ['b']
Other (Constant "ab")

它返回错误列表,如果有的话,或者成功的结果。

这种类型通常称为“验证”应用程序。 Hackage上有other implementations。一种可能的改进是将故障容器的要求放宽为Monoid,同时允许Semigroups。

注意Errors 类型不是Monad。但是您可以使用 Data.Functor.Compose 将其与其他 Applicatives 结合使用。


ExceptTMonadPlus 实例具有相关但不相同的行为:它返回第一个成功(如果有)或错误列表:

ghci> throwE ['a'] `mplus` return () `mplus` throwE ['b'] :: ExceptT [Char] Identity ()
ExceptT (Identity (Right ()))
ghci> throwE ['a'] `mplus` throwE ['b'] :: ExceptT [Char] Identity ()
ExceptT (Identity (Left "ab"))

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-04-04
    • 1970-01-01
    • 1970-01-01
    • 2014-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多