2012-09-05 33 views
5

我很想知道为什么scala.Either不是作为monad完成的设计决定。已经存在关于如何正确的偏置Either,例如一些讨论:为什么斯卡拉不是一个monad?

但也有提到太多细节,我不能让完整地了解它为什么完成的原因。有人可以概述一下正确的偏好Either,关于这样做的问题以及没有正确的偏好Either(如果他们甚至存在)的好处吗?

+0

没有真正回答这个问题,但是如果您查看Scalaz的“验证”,这似乎是您要查找的内容,或多或少。 – adelbertc

回答

7

我认为它只是归结为Principle of Least Astonishment。使用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表达。这是有道理的,在bar是失败的情况下,所以这是结果,但想象如果EitherRight-偏置。上面的代码将编译没有.right预测中的表达,如:

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

如果你在代码中使用Either仅仅是一个“一或-的 - 其他”类型,则可以通过将感到惊讶(1 )这将编译的事实和(2)它返回Left(1)并且看起来从不执行baz

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

+0

+1这个令人印象深刻的例子。 – Frank

5

我不知道这是否是原因,但至少有一个很好的理由。在斯卡拉,for理解需要更多的参数,而不是它是一个monad为了获得完整的功能。特别是,有喜欢

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

结构需要的单子是一个单子,用零(所以如果条件不满足,你可以清空)。

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

一种方法是说:好吧,好吧,就是不要用这种方式来理解。另一种方式是说:好吧,好吧,不要打扰做一个monad。当然,这是一个个人喜好的问题,但是我可以看到,当你尝试使用全功率for给你时,在它的脸上会出现Either(在Scala中提供的常见单子之一中独一无二)的优雅。