代表多个失败案例但只有一个成功案例的惯用类型是什么?

What’s the idiomatic type to represent multiple failure cases but only one success case?

类型 Maybe a 表示可能会失败的计算,其语义我们并不关心 如何 它失败了。如果计算成功,则可能会返回 a 类型的任何值。

相反的情况呢,计算可能由于多种原因而失败(并且我们想保留该信息)但成功不涉及除“是的,它成功了”之外的任何信息?我可以想到两种对这种计算进行编码的明显方法:

Haskell是否有更地道的方式来表示“多个失败案例,但只有一个成功案例”?

在没有看到实际代码的情况下,实际上很难理解失败的含义。如果它是一个纯函数,那么我看不出使用 Maybe 会有什么问题。我从来没有真正将 Nothing 视为失败,但就是这样:没什么。根据上下文,我要么 return Nothing as well,要么使用默认值并继续。我理解可以看做是失败,但更多的还是要看角度 如果调用者不是函数本身。 现在,您想表示一个可能会失败但 return 什么都没有的计算。如果它是一个纯函数,那没有意义。你的功能是纯粹的,什么都没有发生(没有副作用),你也没有得到结果。所以在成功的情况下,你实际上没有计算任何东西:那不是成功,那什么都不是。 ATHI 如果你失败了,你就有失败的原因。这与 returning Maybe.

的简单检查没有什么不同

例如,您可能需要检查某个域是否在黑名单中。为此,您在列表中进行查找:没有什么意味着它很好,即使这意味着它是从您的角度来看和失败并且需要停止您的计算。相同的代码可用于检查您的域是否属于白名单。在那种情况下,没有什么是失败的:仅取决于上下文。

现在,如果你是 运行 一个单子操作(比如保存文件或其他东西),那么 return 除了可能发生不同的故障(磁盘已满,路径不正确等)之外什么都没有意义.我们不关心结果的 IO 的标准签名是 IO (),因此您可以选择 IO (Either e ())(每个人都会理解)或选择 IO () 并引发异常(如果他们真的很特别)。

从问题中不清楚计算可能会如何失败。

如果它类似于编译器,可能会产生很多错误消息(而不是在第一个错误消息时停止),那么您需要类似的东西:

type MyResult a = Either [Error] a

结果成功或失败的原因列表。

另一方面,如果您有一个不确定的计算,其中每个变化都可能成功或失败,那么您需要更像:

type MyResult a = [Either Error a]

然后搜索结果列表。如果你找到一个 Right 然后 return 它,否则 assemble Lefts 的列表。

一个简短的方法是使用 Either e ()pattern synonym

pattern Success :: Either e ()  -- Explicit type signature not necessary
pattern Success = Right ()

你也可以包括一些其他的东西,如果它提高可读性,比如

type FailableWith e = Either e ()

pattern FailedWith :: e -> FailableWith e
pattern FailedWith x = Left x

Maybe 不同,Either 的优势在于所有现有机制都已经到位:FunctorApplicativeMonadFoldableTraversableSemigroup 甚至 OrdLeft x < Right y 应该始终保持)实例可能已经完全按照您希望的错误处理方式运行。一般来说,对于这种特殊情况,Maybe 会倾向于做与你想要的相反的事情(通常你想继续成功并在第一次失败后停止,这与大多数 Maybe 机器将提供这种情况)。