July 25, 2008, Friday, 206

Scala Either

From Workingmouse Wiki

Jump to: navigation, search

A new data type appears in version 2.7.1 of the Scala Programming Language called scala.Either (hereon referred to as Either) that is used very often in every-day practical programming tasks. In a similar way that Scala's List and Option types are classes with one or more case class subtypes, so is Either — it has two case classes; Left and Right. Consider the following shorthand notation that denotes scala.List. This notation uses the pipe symbol to separate the two constructors (i.e. case classes) for a List, which are Nil and :: (pronounced cons) and each constructor name is followed by its arguments. Nil takes no arguments, while cons takes two arguments; one of type A and the other of type List[A].

forall A. List[A] = Nil | :: A List[A]

Similarly, the scala.Option data type may be denoted as

forall A. Option[A] = None | Some A

This data type is similar to a List, however, it doesn't refer to itself in any of its constructor arguments as List does. One may think of Option as a list that always has zero or one element. Others think of Option as a type-safe and more useful representation of null.

Using the same notation, the Either data type looks this

forall A. forall B. Either[A, B] = Left A | Right B

However, notice that Either takes two type variables, while List and Option take one. This means that Either has a different kind to that of List and Option. As a result, functions such as map and flatMap cannot be exposed on Either directly, but instead on left and right projections. For example, to use map on the left side of an Either object reference called e, you would write e.left.map(...).

We might think of Either as a value of either this type (A) or that type (B). An often cited argument against inflexible static type systems is the inability to "return a value of one type or another". For example, a function may wish to return an integer or a string depending on its input and this use-case can be cumbersome to express. The Either type is both expressive and statically type-checked by utilising Scala's flexible static type system.

Pattern Matching Cheat Sheet

It is preferable to use specific functions defined on a type rather than repeat the same pattern by manually pattern matching. Following are some examples that pattern match but are better written using a function that already exists. Since Either is symmetrical on the Left and Right sides, these examples apply only to the Left side, but an equivalent exists for the Right and is omitted for brevity. The examples use free variables 'e' that represents any value of the Either type, 'x' to represent any value and 'f' to represent any function that type-checks in the given context.

isLeft/isRight

e match {
  case Left(_) => true
  case Right(_) => false
}

// Better written as e.isLeft

swap

e match {
  case Left(a) = Right(a)
  case Right(b) => Left(b)
}

// Better written as e.swap

exists

e match {
  case Left(a) => f(a)
  case Right(_) => false
}

// Better written as e.left.exists(f)

forall

e match {
  case Left(a) => f(a)
  case Right(_) => true
}

// Better written as e.left.forall(f)

filter

e match {
  case Left(a) => if(f(a)) Some(a) else None
  case Right(_) => None
}

// Better written as e.left.filter(f)

getOrElse

e match {
  case Left(a) => a
  case Right(_) => x
}

// Better written as e.left.getOrElse(x)

get

e match {
  case Left(a) => a
}

// Better written as e.left.get

map

e match {
  case Left(a) => Left(f(a))
  case Right(b) => Right(b)
}

// Better written as e.left.map(f)

flatMap

e match {
  case Left(a) => f(a)
  case Right(b) => Right(b)
}

// Better written as e.left.flatMap(f)

foreach

e match {
  case Left(a) => f(a)
  case Right(_) => {}
}

// Better written as e.left.foreach(f)

toOption

e match {
  case Left(a) => Some(a)
  case Right(_) => None
}

// Better written as e.left.toOption

toSeq

e match {
  case Left(a) => Seq.singleton(a)
  case Right(_) => Seq.empty
}

// Better written as e.left.toSeq

Use for exceptions

Just as Option can be used in place of null, Either can be used in place of exceptions. Suppose a function that returns a type T but may throw a SillyException. Instead of throwing the exception, the return type of the function may be changed to Either[SillyException, T] and it is up to the user to pattern match on the result to deconstruct it into either its Left or Right part. By historical convention, where Either is being used to denote possible "failure", the failure is specified on the Left while the successful result is on the Right.

This use case is not necessarily limited to exceptions. For example, a user may wish to have an error message for the failing condition instead i.e. Either[String, T]. A caller of this function then deconstructs the result using exhaustive, non-overlapping pattern matching:

f match {
  case Left(msg) => println(msg)
  case Right(t) => handle(t)
}

Set Theory

The Either type represents the concept of the disjoint union, tagged union, variant, variant record or discriminated union. See Wikipedia's description of the Tagged Union.

Image:Disjoint-union.PNG


The Curry-Howard Isomorphism

The C-H Isomorphism is a work by Haskell Curry and William Howard that observes the isomorphic relationship between structural logic and type theory by stating that in order to prove any logical theorem, construct a type to reflect that theorem then find a value that has that type (ignoring the ⊥ value). Under this system, the Either type represents logical disjunction. When discussing disjunction in the context of computer programming, it is often referred to as OR and denoted with the symbol ||. In logic, disjunction is represented with the symbol or where only ASCII characters are available \/ (back slash, forward slash).

If we have two logical propositions, P and Q, we denote their disjunction as P ∨ Q and wish to prove this proposition (i.e. promote it to a theorem). In order to do this, then we must prove either P or Q as theorems by finding a value of the type P or a value of the type Q. The Either type is that value that corresponds to the disjunctive proposition P ∨ Q.

Links