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

标签 scala monads

考虑以下组合

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 接口(interface)中没有任何内容强制您对 LeftRight 大小写使用不同的类型。特别是,Left类型参数可以与Right类型参数相同,它们都可以等于Result(或“PartialSuccess"?),您可以在其中定义 Result 的构成。

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

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

最后,您将其折叠为一个结果:

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

如果我理解正确,您可能想到的所有其他单子(monad) M 本质上与 Either[Result, Result] 相同,但有一些特殊的 getResult 方法,相当于.fold(identity, Identity),因此不需要增加不必要的实体。

关于scala - 如何评估对链中最后成功步骤的理解?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50204765/

相关文章:

generics - Scala 中基类和所有派生类的模式匹配

haskell - 返回从 monad 中提取的元素;多余的?

haskell - 如何创建一个允许 IO 但不是 MonadIO 的 monad?

haskell - 在其他一些 monad m1 中绑定(bind)一个 Monadic 值 (m2 a)

haskell - 如何用bind来定义apply?

F# 自定义计算工作流程

scala - 新的 dotty 运行时对我来说完全消失了

scala - 警告 :(55, 56) MoldPiece[PressureData(Int, Prettyprint.YesNo)] 上尚不存在 `withFilter' 方法,请改用 `filter' 方法

scala - scala 中的问题 `object Foo { val 1 = 2 }`

scala - 如何根据另一个数据帧过滤一个 Spark 数据帧