5

我有兴趣了解设计决策为什么scala.Either不作为单子完成。已经存在一些关于如何右偏的讨论Either,例如:

但是提到了太多细节,我无法完整地了解为什么要这样做。有人可以概述一下偏右的好处,Either这样做的问题以及不偏右的好处Either(如果它们甚至存在的话)吗?

4

2 回答 2

8

我认为它只是归结为最小惊讶原则。使用Either来编码成功或失败显然是人们所做的事情,但它并不是Either. 事实上,除了传统之外,没有太多的Right成功和Left失败的理由。正如adelbertc 上面提到的评论,scalaz 有Validation专门编码这个。

为了进一步证明上述 POLA 声明的合理性,请使用以下代码:

def foo(): Either[Int, Int] = Right(1)
def bar(j: Int): Either[Int, Int] = Left(1)
def baz(z: Int): Either[Int, Int] = Right(3)

// Result is Left(1) 
for (a <- foo().right; b <- bar(a).right; c <- baz(b).right) yield c

这是编译的,因为我在表达式中使用了.right投影。for这是有道理的Left(1)inbar是失败的情况,所以这就是结果,但想象一下如果EitherRight-biased。.right上面的代码将在没有表达式中的投影的情况下编译,例如:

for (a <- foo(); b <- bar(a); c <- baz(b)) yield c

如果您Either在代码中使用的只是“一种或另一种”类型,您会惊讶于 (1) 这会编译的事实和 (2) 它返回Left(1)并且似乎从不执行的事实baz

总之,Validation如果你想用它Either来编码成功或失败,请使用。

于 2012-09-06T05:10:46.450 回答
5

我不知道这是否是最初的原因,但至少有一个很好的理由。在 Scalafor中,为了获得完整的功能,理解需要更多的参数而不是单子。特别是,有像

for (a <- ma if a > 7; /*...*/) yield /*...*/

这要求 monad 是一个 monad-with-zero (所以如果条件失败,你可以清空它)。

Either不能明智地是一个带零的单子(除了Either[Unit,B],其中Left(())可以是零)。

一种方法是说:好吧,好吧,只是不要那样使用你的理解。另一种方法是说:好吧,好吧,根本不用费心让 Either 成为一个 monad。Either当然,这是个人喜好问题,但我可以看到,一旦您尝试使用所提供的全部功能,(在 Scala 中提供的常见 monad 中是独一无二的)就显得缺乏优雅for

于 2012-09-06T00:02:00.133 回答