2

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, i.e. 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))
Kevin Meredith
  • 41,036
  • 63
  • 209
  • 384

4 Answers4

6

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.

Jörg W Mittag
  • 363,080
  • 75
  • 446
  • 653
  • `Haskell makes it into a monad by favoring one of the two types over the other`. When you say `favor`, does that mean the assumption that `Right` is success and `Left` indicates failure? – Kevin Meredith Aug 24 '14 at 13:48
  • 4
    @KevinMeredith: "favor" means simply that `return` will just return the right side, and `>>=` will simply bind the right side and ignore the left side or pass it through unchanged. This means that the right side is favored over the left side, we usually say it is "right-biased". But there's no real reason to do so, *unless* you use `Either` for errors and you assume that `Right` is success. But there are other uses of `Either`, and even if you use it for errors, then putting the error right and the success left is equally valid. – Jörg W Mittag Aug 24 '14 at 14:54
5

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).

0__
  • 66,707
  • 21
  • 171
  • 266
  • Thanks. But why doesn't Either have flatMap as a method? – Kevin Meredith Aug 24 '14 at 01:44
  • 1
    @KevinMeredith see the last linked blog. `scala.util.Either` is unbiased and therefore not a monad itself, only via the projections. If you want a right-biased variant with direct monadic interface, the Scalaz one is for you, or (see answer of @LimbSoup) use `Try`. _Why_ it was designed that way, I don't know. – 0__ Aug 24 '14 at 01:51
  • 1
    This answer is valid only for Scala version < 2.12. Check my answer https://stackoverflow.com/a/61244126/2219550 about newer version of Scala where `Either` support `flatMap` – shobull Apr 16 '20 at 06:40
1

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.
Michael Zajac
  • 55,144
  • 7
  • 113
  • 138
  • 2
    and these right/left projection make things WORSE, because they confusingly have methods named "map" and "flatMap" which have similar but different signatures then what you would expect. Normally, map would be the map we know from Functor, which would be F[A] => (A => B) => F[B], but here it is RightProduction[A] => (A => B) => Either[A] (why isn't the return type RightProjection[B]) ? similarly, the return type of flatMap is Either[B] instead of RightProjection[B]. grrr – stew Aug 24 '14 at 01:52
1

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 e.g. this:

for {
 right1 <- either1
 right2 <- either2
} yield (righ1 + right2)
shobull
  • 3,690
  • 1
  • 19
  • 26