问题
I'm interested in knowing the design decisions why scala.Either
was not done as a monad. There already exists some discussion on how to right-biasing Either
, for example:
- right-biasing Either
- fixing Either
- Fixing scala.Either - unbiased vs biased
But there are mentioned too much details and I couldn't get an complete overview about why it is done as it is done. Can someone give an overview about the benefits of having a right-biased Either
, about the problems to do it that way and about the benefits of not having an right-biased Either
(if they even exist)?
回答1:
I think it just comes down to the Principle of Least Astonishment. Using Either
to encode success or failure is clearly something people do, but it is not the only use of Either
. In fact, there is not much reason to have Right
be success and Left
be failure other than tradition. As adelbertc's comment above mentions, scalaz has Validation
which specifically encode this.
To further justify the POLA claim above, take this code:
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
This compiles because I am using the .right
projection in the for
expression. It makes sense here the Left(1)
in bar
is the failure case and so that is the result, but imagine if Either
was Right
-biased. The above code would compile without the .right
projections in the expression like:
for (a <- foo(); b <- bar(a); c <- baz(b)) yield c
If you used Either
in your code to just be a "one-or-the-other" type, you would be surprised by (1) the fact that this would compile and (2) that it returns Left(1)
and seemingly never executes baz
.
In summary, use Validation
if you want to use Either
to encode success or failure.
回答2:
I don't know if this was the original reason, but there is at least one good reason. In Scala, for
comprehensions require more from the argument than that it is a monad in order to gain full functionality. In particular, there are constructs like
for (a <- ma if a > 7; /*...*/) yield /*...*/
which require that the monad be a monad-with-zero (so you can empty it if the condition fails).
Either
cannot sensibly be a monad-with-zero (save for Either[Unit,B]
, where Left(())
can be the zero).
One way to go is to say: okay, fine, just don't use your for-comprehensions that way. Another way to go is to say: okay, fine, don't bother making Either a monad at all. It's a matter of personal preference, of course, but I can see a certain lack of elegance in having Either
(uniquely among the common monads provided in Scala) fall flat on its face once you try to use the full power for
gives you.
来源:https://stackoverflow.com/questions/12290858/why-is-scalas-either-not-a-monad