🎓 A1Learner
🔍
0 of 48 lessons completed

Scala Either in Depth

An Either value is a value that is either a Left reason or a Right result. In depth, Either means chaining steps that can fail with a reason.

Map transforms Right and passes Left through

Doubling Right 10 gives Right 20. Doubling Left bad leaves the reason unchanged.

@main def main(): Unit =
  val r: Either[String, Int] = Right(10)
  println(r.map(_ * 2))
  val l: Either[String, Int] = Left("bad")
  println(l.map(_ * 2))

FlatMap chains steps that return Either

safeDiv returns a reason for division by zero. 20 divided by 4 is 5, and dividing that by 5 gives 1.

@main def main(): Unit =
  def safeDiv(a: Int, b: Int): Either[String, Int] = if b == 0 then Left("zero") else Right(a / b)
  println(safeDiv(20, 4))
  println(safeDiv(20, 0))
  println(safeDiv(20, 4).flatMap(x => safeDiv(x, 5)))

Fold handles both sides in one call

Fold takes the length of a Left reason and doubles a Right value. The reason oops has length 4.

@main def main(): Unit =
  val r: Either[String, Int] = Right(10)
  val l: Either[String, Int] = Left("oops")
  println(r.fold(s => s.length, v => v * 2))
  println(l.fold(s => s.length, v => v * 2))

Example

@main def main(): Unit =
  def parseAge(s: String): Either[String, Int] =
    s.toIntOption match
      case Some(n) if n >= 0 => Right(n)
      case _ => Left("bad age")
  println(parseAge("20").map(_ + 1))
  println(parseAge("abc"))
  println(parseAge("20").fold(e => e, n => s"age $n"))

Key points

  • Left: the side that carries a reason for failure.
  • Right: the side that carries the successful result.
  • Map on Either: transforms a Right value and passes a Left through untouched.
  • FlatMap on Either: chains a step that returns an Either, without nesting.
  • Fold on Either: handles both sides with one function for each side.

In this example, parseAge turns a text age into an Either with a reason for bad input. Adding 1 to the parsed 20 gives Right 21, while abc gives Left bad age. Fold turns the good age into a plain message.

Note

the right side is the correct side by convention. Code that reads an Either should expect the result on the right.

Try it Yourself

Edit the code, then press Run.

Running is simulated · Scastie

Exercise

What is Left("err").map(_ * 2) when the value has type Either[String, Int]?