Published 2014-01-12.
Last modified 2016-10-14.
Time to read: 6 minutes.
Either
is a Scala type that can hold a value which has one of two possible types. This lecture compares and contrasts Either
, Try
and Option
.
The sample code for this lecture can be found in
courseNotes/
.
Scala's Either
type holds information about entities which can assume one of two states.
An Either
instance can only hold one value,
which is either wrapped by a Left
instance or a Right
instance.
If an Either
instance is of type Right
,
we say that the instance is a Right;
if an Either
instance has type Left
, we say that the instance is a Left.
Either
is immutable, so once an instance has been assigned a value it cannot be changed.
Either
is parametric in two types, which are often different from each other.
We will discuss parametric types (also known as generics) in detail in the
Parametric Types lecture of the
Intermediate Scala course.
For example, you could decide that information about live things will be a Right
,
and information about non-living things will be Left
.
Either
wraps both possibilities.
Right
and Left
are subclasses of Either
,
and are stored into the right
and left
properties of Either
instances,
respectively, as shall see in a moment.
We can refer to the value of the right
property as the right projection,
and the value of the left
property as the left projection.
Declare the Type
You could declare an immutable value of type Either[NonLivingThing, LivingThing]
and assign it a value.
scala> case class LivingThing(name: String, species: String) defined class LivingThing
scala> case class NonLivingThing(name: String, description: String) defined class NonLivingThing
scala> val thing1: Either[NonLivingThing, LivingThing] = Right(LivingThing("Leatherback Turtle", "Dermochelys coriacea")) thing1: Either[NonLivingThing,LivingThing] = Right(LivingThing(Leatherback Turtle,Dermochelys coriacea))
Notice that I wrapped the LivingThing
instance within a Right
instance.
The Scala compiler is not smart enough to figure out that a LivingThing
belongs on the Right
.
scala> val thing1: Either[NonLivingThing, LivingThing] = LivingThing("Leatherback Turtle", "Dermochelys coriacea") scala> <console>:15: error: type mismatch; found : LivingThing required: Either[NonLivingThing,LivingThing] val thing1: Either[NonLivingThing, LivingThing] = LivingThing("Leatherback Turtle", "Dermochelys coriacea")
Also notice that I declared the full type of thing1
.
If I did not do that, the Left
would have type Nothing
.
scala> val thing3 = Right(LivingThing("Leatherback Turtle", "Dermochelys coriacea")) scala> thing1: scala.util.Right[Nothing,LivingThing] = Right(LivingThing(Leatherback Turtle,Dermochelys coriacea))
Similarly, here is how to create an instance using Left
:
scala> val thing2: Either[NonLivingThing, LivingThing] = Left(NonLivingThing("Opal", "Hydrated silica")) scala> thing2: Either[NonLivingThing,LivingThing] = Left(NonLivingThing(Opal,Hydrated silica))
Similar Left and Right Types
This example shows the Left
and Right
both having the same type, String
.
Here is an Either[String, String]
.
scala> val result1: Either[String, String] = Right("yay!") scala> result1: Either[String,String] = Right(yay!)
You can test to see if an Either
instance holds its value on the left
or on the right
.
scala> result1.isRight scala> res0: Boolean = true
scala> result1.isLeft res1: Boolean = false
Storing a value into Either.left
is similarly simple.
scala> val result2: Either[String, String] = Left("Oops, I did it again!") scala> result2: Either[String,String] = Left(java.lang.String)
scala> result2.isRight scala> res3: Boolean = false
scala> result2.isLeft scala> res4: Boolean = true
Extract the Value
Here is one way to extract the value from the right projection of an Either
instance.
We discussed extractors in the
Unapply and
Sealed Classes and Extractors
lectures earlier in this course.
scala> val Right(right) = result1 scala> right: String = yay!
Scala 2.12 introduced the value
property for Right
and Left
,
so we can also write:
scala> val rightAgain = result1.value scala> rightAgain: String = yay!
We can also use an extractor to retrieve the value from a Left
:
scala> val Left(left) = result2 scala> left: String = String: Oops, I did it again!
This also works:
scala> val leftAgain = result2.value scala> leftAgain: String = String: Oops, I did it again!
A common use of Either
is as an alternative to Option
for dealing with
possible failures, because it can return information about a failure.
For example, you could use Either[String, Int]
to decode a String
into an Int
on the Right
,
or return the unparseable string on the Left
.
def parse(in: String): Either[String, Int] = try { Right( t) } catch { case e: Exception => Left(in) }
def show(either: Either[String, Int]): Unit = println(either match { case Right(x) => s"Parsed Int: $x"
case Left(x) => s"Unparseable String: $x" })
Now let's try parsing some strings:
scala> show(parse("1234")) scala> Parsed Int: 1234
scala> show(parse("12abc")) Unparseable String: 12abc
scala> show(parse("abc123")) Unparseable String: abc123
Many methods might return a different type of value when an error occurs.
Since Scala 2.10 we have the
scala.util.Try
type,
described in the Try and try/catch/finally lecture.
Try
is similar to Either
, but with an Exception
on the left side.
If you find yourself wanting to return an Either
,
with an Exception
on the left side for the failure case,
you should return a Try
instead.
However, many uses for Either
do not require the value on the right to mean success
and the value on the left to mean failure.
Unlike
The Scala 2.12 Changes section discusses the extra capabilities added to Try
and Option
, Either
is not right-biased;
this means that Either
has been designed to give equal weight for the Left
and
Right
subclasses.
You'll realize how this affects your code as you work with Either
, Try
and
Option
.Either
with Scala 2.12,
and the Option vs. Either vs. Try
section at the end of this lecture contrasts these three types.
Processing Either Efficiently with fold

As we have just seen, Either
can hold one of two values.
What if you wanted to write code that checks to see if the result was a Right
or a Left
,
and return the same type of result, say a String
, for display?
It would be desirable to be able to write code that handles both cases without writing a lot of boilerplate.
This use case is handled by the
fold
combinator,
which is a higher-order function that accepts two Function1
s,
one for each of the Left
and Right
cases.
Higher-order functions will be discussed in detail in the Higher-Order Functions lecture of the Intermediate Scala course.
Here is an example of what fold
looks like in action:
scala> result2.fold( | lhs => "Handled left side", | rhs => "Handled right side" | ) scala> res0: String = Handled left side
It would be difficult to understand your first encounter with fold
if you never looked at the
Either
class definition and the fold
method signature at least once.
This is partially because Either.fold
specifies the type of each of the Function1
s
so we do not need to declare the types of the lambdas shown above.
The Either
class declaration shows that it is parametric in A
and B
;
the type of the Left
side of Either
is A
,
and the type of the Right
side of Either
is B
.
To refresh your memory, result2
was defined like this:
val result2: Either[String, String] = Left("Oops, I did it again!")
This declaration told the Scala compiler that parametric types A
and B
are both actually
String
for this instance of Either
.
The fold
method signature is:
fold[C](fa: A => C, fb: B => C): C
This means that fold
is parametric in C
,
and accepts two Function1
s that both return the same parametric type, namely C
.
From the fold
method signature,
the Scala compiler knows that fa
(on the Left
) has type A => C
and
fb
(on the Right
) has type B => C
.
In other words, the first Function1
, fa
,
accepts an A
(which is the type of the Left
side of this Either
)
and returns a C
,
while the second Function1
, fb
, accepts a B
(which is the type of the Right
side of this Either
)
and also returns a C
.
If both fa
and fb
do not return the same type the compiler will issue an error.
Again, fold
requires that both Function1
s passed to it return the same type,
and that type is referred to as C
in the fold
method signature.
The Scala compiler deduces that C
must be String
for this fold
invocation.
This means that the Scala compiler knows that the types of fa
and fb
are both actually String => String
for this invocation of fold
.
You do not need to declare this explicitly,
but if you want to express the types written explicitly you could write this instead:
scala> result2.fold[String]( | (lhs: String) => "Handled left side", | (rhs: String) => "Handled right side" | ) scala> res5: String = Handled left side
In the above, the first type, in square braces, declares C
to be String
.
The type of lhs
reaffirms A
to be String
;
remember that when the Either
instance was created,
A
was defined to be String
,
so if you put any other type here the compiler will give an error.
Let's try it and see:
scala> result2.fold[String]( | (lhs: Int) => "Handled left side", | (rhs: String) => "Handled right side" | ) scala> <console>:10: error: type mismatch; found : Int => String required: String => String (lhs: Int) => "Handled left side",
Similarly, the type of rhs
reaffirms B
to be String
;
again, B
was declared as String
when the Either
was created.
If we explicitly declare C
to be a specific type,
that type must match the inferred type deduced by the compiler.
Let's see what happens when we declare C
to be something other than String
:
scala> result2.fold[Int]( | (lhs: String) => "Handled left side", | (rhs: String) => "Handled right side" | ) scala> <console>:10: error: type mismatch; found : String("Handled left side") required: Int (lhs: String) => "Handled left side", ^ <console>:11: error: type mismatch; found : String("Handled right side") required: Int (rhs: String) => "Handled right side"

Type Alias
We can define a type alias using the type
keyword.
It is usually better to define a type alias with a descriptive name than to write out a long type
like Either[String, Int]
.
type StringOrInt = Either[String, Int]
Let's use the type alias to shorten the above code.
def parse(in: String): StringOrInt = try { Right(in.toInt) } catch { case e: Exception => Left(in) }
def show(either: StringOrInt): Unit = println(either match { case Right(x) => s"Parsed Int: $x"
case Left(x) => s"Unparseable String: $x" })
Exercise
The Either
type in the Scala library can be used for algorithms that return
either a result or some failure information.
Write a method that takes two parameters: a list of words and a word to match.
Return an Either
containing the index of the matching word in the list on the
right or the word that did not match on the left.
To create a console application, we will clone the
sbtTemplate
project on GitHub that we learned about in
SBT Project Setup lecture.
We will clone into a directory called eitherExercise
.
$ git clone https://github.com/mslinn/sbtTemplate.git eitherExercise
$ cd eitherExercise
Now lets edit a new file in eitherExercise
called src/main/scala/WordSearch.scala
using an IDE or your favorite text editor.
To define an entry point in that file, simply write:
object WordSearch { def main(args: Array[String]): Unit = { } }
Let's define a type alias for the return type, inside the body of WordSearch
:
object WordSearch { def main(args: Array[String]): Unit = { type StringOrInt = Either[String, Int] } }
Let's also decide on what the signature will be for the method that will do the work.
Note that ???
defines a method body that does nothing –
it is a placeholder for the body which we will write later.
This allows the code to compile before it is completely written.
object WordSearch { def main(args: Array[String]): Unit = { type StringOrInt = Either[String, Int]
def search(list: List[String], word: String): StringOrInt = ??? } }
We will use this code to run the search
method:
List("word", "oink", "blahbla", "another").foreach { w => println(s"$w: ${search(list, w)}") }
So we now have:
object WordSearch { def main(args: Array[String]): Unit = { type StringOrInt = Either[String, Int]
def search(list: List[String], word: String): StringOrInt = ???
List("word", "oink", "blahbla", "another").foreach { w => println(s"$w: ${search(list, w)}") } } }
Notice that the entry point application consists of a type alias, a method definition and some code that is executed.
Solution
Some solutions are provided in
courseNotes/
.
Examine each one – you will learn something with each solution.
package solutions
/** Two solutions are shown. Solution 2 is best. */ object WordSearch extends App { val list = List("word", "another", "more")
type StringOrInt = Either[String, Int]
/** Efficient but clumsy */ def search(list: List[String], word: String): StringOrInt = { val index = list.indexOf(word) if (index == -1) Left(word) else Right(index) }
/** Efficient, simple, elegant. * Here we see Scala's match keyword used as a multi-way branch. * Each match is tried in order until one succeeds. * In the second case, notice that the variable index is defined. It will match every value. */ def search2(list: List[String], word: String): StringOrInt = list.indexOf(word) match { case -1 => Left(word) case index => Right(index) }
List("word", "oink", "blahbla", "another").foreach { w => println(s"Method 1 search for '$w': ${search(list, w)}") println(s"Method 2 search for '$w': ${search2(list, w)}") } }
You can run them like this:
$ sbt "runMain solutions.WordSearch" Method 1 word: Right(0) Method 2 word: Right(0) Method 1 oink: Left(oink) Method 2 oink: Left(oink) Method 1 blahbla: Left(blahbla) Method 2 blahbla: Left(blahbla) Method 1 another: Right(1) Method 2 another: Right(1)
Scala 2.12 Changes
Either
is a right-biased monad, but the changes are backwards-compatible,
so existing code that uses Either
should continue to work.
The following methods have been added:
map
andflatMap
, which means for-comprehensions now can be used.-
contains
,toOption
,toTry
,toSeq
andfilterOrElse
.
Here are the notes for the pull request to the Scala compiler.
Prior to Scala 2.12, Either
did not work directly with for-comprehensions.
We will discuss this topic in detail in the Either is Right-Biased With Scala 2.12
section of the For-Loops and For-Comprehensions Examples lecture of the
Intermediate Scala course.
Option vs. Either vs. Try
Here is a table that provides guidelines for when you might use each of these constructs:
Option | Either | Try | |
---|---|---|---|
No problem encountered | Returns Some(value)
| Returns Right(value)
| Returns Success(value) /td>
|
Problem encountered | Returns None and ignores problem
| Returns Left(value) that contains information about the problem, or original data that could not be processed.
| Returns Failure(exception) that contains Exception for later error handling
|
Use case | Only the happy path matters; no error handling required. Simple to work with. |
Use case #1: Data about failure is as important as the successful result.
Largely supplanted by Try since Scala 2.10.
Use case #2: There is no requirement for Either 's left hand side to have any relationship with
failure – instead, it is possible that the program requires a variable to contain a value with one of two types.
| Successful result is important, also errors must be handled. This is the best choice for most use cases involving error handling. |
© Copyright 1994-2024 Michael Slinn. All rights reserved.
If you would like to request to use this copyright-protected work in any manner,
please send an email.
This website was made using Jekyll and Mike Slinn’s Jekyll Plugins.