0Pricing
Scala for Backend Engineering & Functional Programming · Lesson

Composing Either

map and flatMap.

Composing Either is a free Scala for Backend Engineering & Functional Programming lesson on CoddyKit — lesson 3 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the Scala for Backend Engineering & Functional Programming learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Composing Computations

Real programs chain several fallible steps: parse, validate, look up, compute. Either lets you compose these so that the first failure short-circuits the whole chain.

The tools are map, flatMap, and for-comprehensions.

flatMap Sequences Eithers

flatMap applies a function that itself returns an Either. If the receiver is Left, the function is never called and the Left propagates.

object Main {
  def positive(n: Int): Either[String, Int] =
    if (n > 0) Right(n) else Left("not positive")

  def main(args: Array[String]): Unit = {
    val r = Right(5).flatMap(positive)
    val l = Right(-1).flatMap(positive)
    println(r)
    println(l)
  }
}

Short-Circuiting

When you chain multiple flatMap calls, the first Left stops everything. Later steps are skipped, and that error becomes the final result.

object Main {
  def step(label: String, n: Int): Either[String, Int] = {
    println(s"running $label")
    Right(n + 1)
  }

  def main(args: Array[String]): Unit = {
    val result = Left("early error").asInstanceOf[Either[String, Int]]
      .flatMap(n => step("A", n))
      .flatMap(n => step("B", n))
    println(result)
  }
}

for-Comprehension over Either

Because Either is right-biased, you can use it in a for-comprehension. Each <- unwraps a Right; any Left stops the comprehension and becomes the result.

object Main {
  def parse(s: String): Either[String, Int] =
    s.toIntOption.toRight(s"bad: $s")

  def main(args: Array[String]): Unit = {
    val sum = for {
      a <- parse("3")
      b <- parse("4")
    } yield a + b
    println(sum)
  }
}

A Failing for-Comprehension

If any step in the comprehension yields a Left, the whole expression is that Left and subsequent steps do not run.

object Main {
  def parse(s: String): Either[String, Int] =
    s.toIntOption.toRight(s"bad: $s")

  def main(args: Array[String]): Unit = {
    val sum = for {
      a <- parse("3")
      b <- parse("oops")
      c <- parse("5")
    } yield a + b + c
    println(sum)
  }
}

Chaining Validations

A realistic pipeline: parse a string, then check a business rule, then transform. Each stage returns an Either.

object Main {
  def parse(s: String): Either[String, Int] = s.toIntOption.toRight("not a number")
  def checkRange(n: Int): Either[String, Int] =
    if (n >= 1 && n <= 100) Right(n) else Left("out of range")

  def process(s: String): Either[String, Int] =
    parse(s).flatMap(checkRange).map(_ * 10)

  def main(args: Array[String]): Unit = {
    println(process("7"))
    println(process("500"))
    println(process("x"))
  }
}

map vs flatMap

Use map when your function returns a plain value. Use flatMap when it returns another Either, to avoid a nested Either[String, Either[String, Int]].

@main def run(): Unit = {
  val withMap: Either[String, Int] = Right(2).map(_ + 1)
  val nested: Either[String, Either[String, Int]] = Right(2).map(n => Right(n + 1))
  val flat: Either[String, Int] = Right(2).flatMap(n => Right(n + 1))
  println(withMap)
  println(nested)
  println(flat)
}

Combining Independent Values

A for-comprehension also works when each step does not depend on the previous one. All must succeed for the final yield to run.

object Main {
  def parse(s: String): Either[String, Int] = s.toIntOption.toRight(s"bad: $s")

  def main(args: Array[String]): Unit = {
    val combined = for {
      x <- parse("10")
      y <- parse("20")
      z <- parse("30")
    } yield List(x, y, z).sum
    println(combined)
  }
}

leftMap-Style Error Transformation

Standard library Either has no leftMap, but you can transform the error with swap.map(...).swap or by mapping inside a fold. This keeps error types consistent across a pipeline.

@main def run(): Unit = {
  val e: Either[String, Int] = Left("low-level error")
  val mapped = e.swap.map(msg => s"context: $msg").swap
  println(mapped)
}

Putting It All Together

A small calculator pipeline that parses two numbers and divides, reporting any failure as a typed error.

object Main {
  def parse(s: String): Either[String, Int] = s.toIntOption.toRight(s"bad number: $s")
  def divide(a: Int, b: Int): Either[String, Int] =
    if (b == 0) Left("division by zero") else Right(a / b)

  def calc(x: String, y: String): Either[String, Int] =
    for {
      a <- parse(x)
      b <- parse(y)
      r <- divide(a, b)
    } yield r

  def main(args: Array[String]): Unit = {
    println(calc("20", "4"))
    println(calc("20", "0"))
    println(calc("x", "4"))
  }
}

Why This Matters

Composing Either gives you railway-oriented programming: the happy path flows through Right, and any error diverts onto the Left track and bypasses the rest. No exceptions, no null checks, just values.

Quick Check

Test your understanding of composing Either.

Recap

You learned to compose Either:

  • flatMap sequences fallible steps and short-circuits on the first Left.
  • for-comprehensions read cleanly for multi-step pipelines.
  • Use map for plain results, flatMap for Either-returning functions.
  • Transform errors with swap.map(...).swap.

Frequently asked questions

Is the “Composing Either” lesson free?

Yes — the full text of “Composing Either” is free to read here on the web, and the Scala for Backend Engineering & Functional Programming course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the Scala for Backend Engineering & Functional Programming course, upgrade to CoddyKit PRO.

What will I learn in “Composing Either”?

map and flatMap. You practise Scala for Backend Engineering & Functional Programming with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start Scala for Backend Engineering & Functional Programming?

No prior experience is required. Scala for Backend Engineering & Functional Programming on CoddyKit is structured for beginners through advanced learners; this is — lesson 3 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Composing Either” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this Scala for Backend Engineering & Functional Programming lesson?

Yes. Every Scala for Backend Engineering & Functional Programming lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Either for Errors
  2. Try, Success, Failure
  3. Composing Either
  4. Converting Between Types
← Back to Scala for Backend Engineering & Functional Programming