Scala 为什么flatMap链在第一个左值上停止,但在右值上继续

Scala 为什么flatMap链在第一个左值上停止,但在右值上继续,scala,flatmap,either,Scala,Flatmap,Either,我不明白这句话: Right(1)。flatMap(=>Left(2))。flatMap(=>Left(3)) Right(1)被传递到.flatMap(\u=>Left(2)。它返回Left(2),然后被传递到.flatMap(\u=>Left(3)。它应该返回Left(3)。但它返回Left(2) 为什么会这样 另一个例子是Right(1).flatMap(=>Right(2)).flatMap(=>Right(3)) 它返回右侧(3)(它应该返回) 据我所知,其工作原理如下: Right(

我不明白这句话:
Right(1)。flatMap(=>Left(2))。flatMap(=>Left(3))

Right(1)
被传递到
.flatMap(\u=>Left(2)
。它返回
Left(2)
,然后被传递到
.flatMap(\u=>Left(3)
。它应该返回
Left(3)
。但它返回
Left(2)

为什么会这样

另一个例子是
Right(1).flatMap(=>Right(2)).flatMap(=>Right(3))

它返回
右侧(3)
(它应该返回)

据我所知,其工作原理如下:
Right(1)
传递给
.flatMap(\u=>Right(2))
。它返回
Right(2)
,然后传递给
.flatMap(\u=>Right(3)
。最后返回
Right(3)


原因是从Scala 2.12开始,任何一个都是右偏的。这意味着当结果为左时,像flatMap这样的操作将停止计算。请检查实现以了解它:

def flatMap[EE >: E, B](f: A => Either[EE, B]): Either[EE, B] =
  this match {
    case Left(value)  => Left(value)
    case Right(value) => f(value)
  }

如你所见,在Left的情况下,它构造的左边带有从中提取的值,而不应用f。

flatmap
右边的
相关联。我的意思是它只对
右边的
值进行操作,而不对
左边的
值进行操作。这允许
flatMaps
的序列缩短当它碰到第一个
时退出


更多示例,请参见:

平面映射计算链在第一次评估的
左侧
时短路,原因是
单子在
右侧
值上存在成功偏差。这种偏差的原因是编程人员经常将左侧解释为表示计算的错误结果,whilst右边意味着计算的成功结果。因此,如果左边意味着错误,那么在错误的情况下继续计算就没有多大意义了,因此链就断了

注意,
other
monad过去只根据惯例有偏见。传统的
other
右倾偏见是。一些人认为
other
应该是无偏见的

如果您使用其中任何一个来报告错误,那么您确实需要 它可能偏向于一方,但这只是许多用例中的一个,并且 将单个特殊用例硬编码到 糟糕的设计。对于这种用例,您不妨使用Try, 这基本上也是一种偏见

当其他人认为偏向一方时

…使用Scala 2.12。它变得右倾化,这是一个更好的选择 设计选择,与其他类似的sum类型完美匹配 其他库。例如,现在从其中一个库转到另一个库非常容易 /(scalaz dicjuntion)现在没有偏差不匹配。它们是 完全同构的

尽管如此,
的偏见并没有强迫人们只使用“快乐/不快乐”的语义例如,中的要求可以用
来解决,其中左侧被解释为快乐/成功的值。

或是右偏。这意味着像
映射
&
平面映射
这样的操作只在右侧工作,当您有左侧时,短路。