Skip to content
Option, Try, Either
step 1/5

Reading — step 1 of 5

Learn

~1 min readEffect Types

Scala has three workhorse "box" types for representing operations that can fail or be missing.

Option[A]Some(value) or None. For "value or missing":

val result: Option[Int] = map.get("missing")    // None or Some(n)

result.getOrElse(0)
result.map(_ * 2)
result.flatMap(n => safeDiv(100, n))
result match {
    case Some(n) => ...
    case None => ...
}

Try[A]Success(value) or Failure(throwable). Wraps exception-throwing code:

import scala.util.{Try, Success, Failure}

val n: Try[Int] = Try(input.toInt)
n match {
    case Success(v) => println(s"got $v")
    case Failure(e) => println(s"failed: ${e.getMessage}")
}

Either[L, R]Left(error) or Right(value). By convention Right is success, Left is failure with a typed error:

def parsePort(s: String): Either[String, Int] =
    s.toIntOption match {
        case Some(n) if n > 0 && n <= 65535 => Right(n)
        case Some(n) => Left(s"out of range: $n")
        case None => Left(s"not a number: $s")
    }

For-comprehensions chain them all:

for {
    a <- result1            // pattern: T => Option[T] / Either[E, T] / Try[T]
    b <- result2(a)
    c <- result3(a, b)
} yield c + a

If any step is None/Failure/Left, the whole comprehension short-circuits to that. The for-comprehension desugars to nested flatMap/map.

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…