如何评估对链中最后成功步骤的理解?

How to evaluate a for-comprehension to the last successful step in the chain?

考虑以下组成

for {
  v1 <- transform1(v)
  v2 <- transform2(v1)
  v3 <- transformThatErrors(v2)
  v4 <- transfrom4(v3)
} yield { v4 }

是否有一个 monad M 允许上面的计算结果为 M(v2)

我正在尝试对程序应应用完整转换链的情况进行建模直到第一个失败的转换,在这种情况下,链评估为最后一个成功的转换.在最坏的情况下,整个链表示 identity(v).

EitherOption 这样的 Monad 不符合这个要求,因为在出​​现错误时,它们会将整个链评估为错误,而链必须始终评估为成功。换句话说,我希望程序能做多少就做多少,但如果它什么也做不了,那也没关系。

Either monad 正是您想要的。 Either 的界面中没有任何内容强制您对 LeftRight 情况使用不同的类型。特别是,Left 类型参数可以与 Right 类型参数相同,它们都可以等于 Result(或“PartialSuccess”?),​​其中你定义什么构成 Result.

因此,您只需将所有 transformN 函数声明为 return 类型

def transformN(previousStep: Result): Either[Result, Result] = ???

最后,您 fold 将其合并为一个结果:

val res: Result = (for {
  v1 <- transform1(v)
  v2 <- transform2(v1)
  v3 <- transformThatErrors(v2)
  v4 <- transfrom4(v3)
} yield v4).fold(
  partialRes => partialRes,
  completeRes => completeRes
)

甚至只是

.fold(identity, identity)

一旦第一次转换失败,Either 将把部分结果打包为 Left,return,而不应用任何进一步的转换。如果每个转换步骤都成功,则最终结果将 return 编辑为 Right。无论转换在哪一点停止,最终的 fold 都会从中提取(部分)结果。

如果我理解正确,你可能想出的所有其他 monad MEither[Result, Result] 基本相同,但有一些特殊的 getResult 方法相当于.fold(identity, identity),因此不需要不必要地增加实体。