Skip to content

Instantly share code, notes, and snippets.

@dwins
Created October 15, 2011 19:11
Show Gist options
  • Select an option

  • Save dwins/1290001 to your computer and use it in GitHub Desktop.

Select an option

Save dwins/1290001 to your computer and use it in GitHub Desktop.
/** Represents a value of one of two possible types (a disjoint union.)
* Instances of Either are either an instance of [[scala.Left]] or [[scala.Right]].
*
* A common use of Either is as an alternative to [[scala.Option]] for dealing
* with possible missing values. In this usage, [[scala.None]] is replaced
* with a [[scala.Left]] which can contain useful information.
* [[scala.Right]] takes the place of [[scala.Some]]. Convention dictates
* that Left is used for failure and Right is used for success.
*
* For example, you could use ``Either[Exception, Int]`` to safely parse a String:
*
* {{{
* val maybeAnInt = Console.readLine("Please enter your favorite integer: ")
* val result: Either[Exception, Int] =
* try {
* Right(result.toInt)
* } catch {
* case ex => Left(ex)
* }
* println(
* result.fold(
* i => "So your favorite number is " + i + ", eh?",
* ex => "That's not a number! It caused " + ex
* )
* )
* }}}
*
* You can also use pattern matching to extract values from `Either`: {{{
* result match {
* case Left(i) =>
* "So your favorite number is " + i + ", eh?"
* case Right(i) =>
* "That's not a number! It caused " + ex
* }
* }}}
*
* For use with `for` comprehensions, an `Either` must be projected into
* either its Left or Right value. A projection this way has `map`
* defined to produce a modified copy of the original Either if the projection
* corresponds to the proper either type: a left projection of a Right returns
* the original value unmodified.
*
* {{{
* val l: Either[String, Int] = Left("scala")
* val r: Either[String, Int] = Right(12)
* l.left.map(_.size): Either[Int, Int] // Left(5)
* r.left.map(_.size): Either[Int, Int] // Right(12)
* l.right.map(_.toDouble): Either[String, Double] // Left("scala")
* r.right.map(_.toDouble): Either[String, Double] // Right(12d)
* }}}
*
* Of course, this works with for-comprehensions as well: {{{
* for (s <- l.left) yield s.size // Left(5)
* }}}
*
* Projections define `flatMap` similarly, allowing "chaining" in
* for-comprehensions with multiple scrutinees: {{{
* val l: Either[String, Int] = Left("scala")
* val r: Either[String, Int] = Right(12)
* l.left.flatMap(_ => r): Either[String, Int] // Right(12)
* l.right.flatMap(_ => r): Either[String, Int] // Left("scala")
* r.left.flatMap(_ => l): Either[String, Int] // Right(12)
* r.right.flatMap(_ => l): Either[String, Int] // Left("scala")
* }}}
*
* This also works with for-comprehensions: {{{
* for (s <- l.left; t <- r.left) yield i // Right(12)
* }}}
*
* @author <a href="mailto:[email protected]">Tony Morris</a>, Workingmouse
* @version 1.0, 11/10/2008
* @since 2.7
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment