Looking at Haskell's Either
Monad, there's a >>=
function.
Prelude Map> let add100 = \x -> Right (x+100 :: Int)
Prelude Map> x
Right 5
Prelude Map> x >>= add100
Right 105
Prelude Map> let y = Left "..." :: Either String Int
Prelude Map> y >>= add100
Left "..."
However, why doesn't Scala's Either[A,B]
have a flatMap
, ie equivalent to >>=
function?
scala> e
res5: Either[String,Int] = Right(1)
scala> e.
asInstanceOf fold isInstanceOf isLeft isRight
joinLeft joinRight left right swap
toString
Also, what's the meaning of left
and right
?
scala> e.left
res6: scala.util.Either.LeftProjection[String,Int] = LeftProjection(Right(1))
scala> e.right
res7: scala.util.Either.RightProjection[String,Int] = RightProjection(Right(1))
You can either use fold
which requires two functions, one for left and one for right, or use the right
projection view:
val e: Either[String, Int] = Right(5)
def add100(i: Int): Either[String, Int] = Right(i + 100)
e.fold(identity, add100) // Right(105)
e.right.flatMap(add100) // Right(105)
So the projection views allow you to see an Either
instance as something that will be mapped through the left or right type. This is explained in the Either
scala-doc help file .
If you are familiar with Haskell, the ScalaZ library might be for you, it has its own 'either' abstraction called \\/
(as described here ).
Either
can't have a flatMap
, because Either
is not a monad. Haskell makes it into a monad by favoring one of the two types over the other, but there really is no justification to do so. Either
means "this can be one of two types". Period. It does not give any preferential treatment to one of the two types.
If you use Either
for error reporting, then it is true that you want it to be biased to one side, but that is only one usecase of many, and hardcoding a single special usecase into a general interface smells of bad design. And for that usecase, you might just as well use Try
, which is basically a biased Either
.
left
and right
return a projection of the Either
, which is biased to one side.
However, note that the design and usability of Either
has been debated very often, and it is indeed not exactly a shining beacon of good API design. Which is one of the reasons why Try
and ScalaZ \\/
exist.
Scala's Either
type is unbiased. With types like Try
, Future
, etc, map
and flatMap
operate on the successful state, but with Either
is this is not the case (though Right
is often favored for success). If Either
has no true successful state, which value should flatMap
operate on? Left
or Right
? That's left up to you with projections.
left
and right
are the projections of Either
, which are essentially biased versions of Either
.
val test: Either[String, Int] = Right(1)
test.right.map(_ + 1) // Right-biased, will map the value to Right(2)
test.left.map(_ + 1) // Left-biased, will not operate on the value since it's `Right`, therefore returning Right(1) again.
Scala's
Either
class was redesigned in Scala 2.12. Prior to 2.12, Either was not biased, and didn't implement map and flatMap methods. As the image from the book shows, Either is redesigned in 2.12 to include those methods, so it can now be used in Scala for-expressions as shown.
https://alvinalexander.com/photos/scala-either-left-right-2.12-biased-map-flatmap/
In Scala 2.12 you can you eg this:
for {
right1 <- either1
right2 <- either2
} yield (righ1 + right2)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.