Scala Friends with Benefits

FP Fundamentals: 3. For Comprehensions

May 02, 2020

This article is a part of a series of small articles explaining the most fundamental functional programming design patterns.

Prefer for-comprehension over the chain of map / flatMap / filter / withFilter in most cases (unless it is a single map or filter). Not only is the code in this form easier to read, it is also easier to extend it and to move things around. I hope it is apparent from the examples above. Note: you can usually simplify a chain of filter and map into one call of collect.

Analysing the code

sealed trait Result[+A] {
  def foreach(f: A => Unit): Unit = {
    this match {
      case Failure(reason) => ()
      case Success(value)  => f(value)
    }
  }

  def map[B](f: A => B): Result[B] = {
    this match {
      case Failure(reason) => Failure(reason)
      case Success(value)  => Success(f(value))
    }
  }

  def flatMap[B](f: A => Result[B]): Result[B] = {
    this match {
      case Failure(reason) => Failure(reason)
      case Success(value)  => f(value)
    }
  }
}

final case class Success[A](value: A) extends Result[A]
final case class Failure[A](reason: String) extends Result[A]
for { a <- Success(3) } println(a)
Success(3).foreach(a => println(a))
for { a <- Success(3) } yield a * a
Success(3).map(a => a * a)
for { a <- Success(3) ; b <- Success(4)  } yield a * b
Tuple(Success(3), Success(4)).map((a, b) => a * b)

Rafael Azevedo

Written by Rafael Azevedo.
Software guy with a passion for collaboration and innovation on organisations, systems and technology.
You should follow him on Twitter