scala - 如何评估对链中最后一个成功步骤的理解?
问题描述
考虑以下组成
for {
v1 <- transform1(v)
v2 <- transform2(v1)
v3 <- transformThatErrors(v2)
v4 <- transfrom4(v3)
} yield { v4 }
是否有一个单子M
可以让上述评估为M(v2)
?
我试图模拟一种情况,即程序应该应用整个转换链,直到第一个转换失败,在这种情况下,链评估为最后一个成功的转换。在最坏的情况下,整个链条代表identity(v)
.
Monad 喜欢Either
并且Option
不符合这个要求,因为在出现错误时,它们会将整个链评估为错误,而链总是需要评估为成功。换句话说,我希望程序尽可能多地做,但如果它不能做任何事情,那也没关系。
解决方案
Either
monad正是你想要的。界面中的任何内容Either
都不会强制您使用不同类型的 forLeft
和Right
case。特别是,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)
,所以没有必要不必要地乘以实体。