Using Eithers with Scala "for" syntax

Dan Burton picture Dan Burton · Jun 3, 2012 · Viewed 16.4k times · Source

As I understand it, Scala "for" syntax is extremely similar to Haskell's monadic "do" syntax. In Scala, "for" syntax is often used for Lists and Options. I'd like to use it with Eithers, but the necessary methods are not present in the default imports.

for {
  foo <- Right(1)
  bar <- Left("nope")
} yield (foo + bar)

// expected result: Left("nope")
// instead I get "error: value flatMap is not a member..."

Is this functionality available through some import?

There is a slight hitch:

for {
  foo <- Right(1)
  if foo > 3
} yield foo
// expected result: Left(???)

For a List, it would be List(). For Option, it would be None. Do the Scala standard libraries provide a solution to this? (Or perhaps scalaz?) How? Suppose I wanted to provide my own "monad instance" for Either, how could I do that?

Answer

Daniel C. Sobral picture Daniel C. Sobral · Jun 3, 2012

It doesn't work in scala 2.11 and earlier because Either is not a monad. Though there's talk of right-biasing it, you can't use it in a for-comprehension: you have to get a LeftProject or RightProjection, like below:

for {
  foo <- Right[String,Int](1).right
  bar <- Left[String,Int]("nope").right
} yield (foo + bar)

That returns Left("nope"), by the way.

On Scalaz, you'd replace Either with Validation. Fun fact: Either's original author is Tony Morris, one of Scalaz authors. He wanted to make Either right-biased, but was convinced otherwise by a colleague.