首页 > 解决方案 > 如何评估对链中最后一个成功步骤的理解?

问题描述

考虑以下组成

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

是否有一个单子M可以让上述评估为M(v2)

我试图模拟一种情况,即程序应该应用整个转换链,直到第一个转换失败,在这种情况下,链评估为最后一个成功的转换。在最坏的情况下,整个链条代表identity(v).

Monad 喜欢Either并且Option不符合这个要求,因为在出​​现错误时,它们会将整个链评估为错误,而链总是需要评估为成功。换句话说,我希望程序尽可能多地做,但如果它不能做任何事情,那也没关系。

标签: scalamonads

解决方案


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

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

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就会将部分结果打包为 aLeft并返回,而不应用任何进一步的转换。如果每个转换步骤都成功,则最终结果将返回为Right. 无论转换在哪一点停止,最终fold都会从中提取(部分)结果。

如果我理解正确的话,M你可能想出的每一个其他 monad 基本上Either[Result, Result]与某些特殊的getResult方法相同,即等效于.fold(identity, identity),所以没有必要不必要地乘以实体。


推荐阅读