This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Why and when to use Either?

13 replies
HHB
Joined: 2009-07-21,
User offline. Last seen 42 years 45 weeks ago.

Hey,
What is the advantages of Either ?
Is it the preferred Scala way to handle exception, so no more try catch?
I'm not clear about it.
Thanks for help and time.

Stefan Langer
Joined: 2009-10-23,
User offline. Last seen 42 years 45 weeks ago.
Re: Why and when to use Either?
It's the functional way of returning a value which can be one of two values. Further more it defines map, flatMap, filter and can therefor be used in for comprehensions. It can be used as a error reporting function like in Haskell with left bearing the error and right bearing the expected value but I wouldn't say that it replaces exception handling in Scala. I personally use either whenever I have a situation in which the reported error is an expected result and still use the exception mechanism whenever I want to report unexpected failure.

-Stefan

2010/3/2 HHB <hubaghdadi [at] yahoo [dot] ca>

Hey,
What is the advantages of Either ?
Is it the preferred Scala way to handle exception, so no more try catch?
I'm not clear about it.
Thanks for help and time.
--
View this message in context: http://old.nabble.com/Why-and-when-to-use-Either--tp27753759p27753759.html
Sent from the Scala - User mailing list archive at Nabble.com.


Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: Why and when to use Either?

Scalaz contains Validation [1], which is isomorphic to Either, but it
clearly defines the error and success types, rather than leaving it to
converntion. This makes it easier to use in comprehensions:

import scalaz._
import Scalaz._

val a: Validation[String, Int] = 1.success
val b: Validation[String, Int] = "Can't produce value b".fail
val ab1: Validation[String, Int] = for { aa <- a; bb <- b} yield aa + bb
// Or, as an Applicative Functor
val ab2: Validation[String, Int] = (a <*> b) apply { _ + _ )

If you choose a container type like NonEmptyList for the errors, it
can also accumulate multiple errors. On trunk, we've added a type
alias to make this easier.

type ValidationNEL[E, A] = Validation[NonEmptyList[E], A]

With this you do some neat stuff like turning a List of Validations
into a Validation of a List.

val listOfVals: List[ValidationNEL[String, Int]] = lines.map(parseInt(_))
// Sequence the List using the Validation Applicative Functor.
val valOfList: ValidationNEL[String, List[Int]]
= listOfVals.sequence[PartialApply1Of2[ValidationNEL,
String]#Apply, Int]

If all lines parsed successfully, you get the List[Int], otherwise you
get the NonEmptyList[String] containing all the error message.

I'll update the example [2] soon to demonstrate step-by-step how this works.

-jason

[1] http://github.com/scalaz/scalaz/blob/master/core/src/main/scala/scalaz/V...
[2] http://github.com/scalaz/scalaz/blob/master/example/src/main/scala/scala...

On Tue, Mar 2, 2010 at 12:05 PM, Stefan Langer
wrote:
> It's the functional way of returning a value which can be one of two values.
> Further more it defines map, flatMap, filter and can therefor be used in for
> comprehensions. It can be used as a error reporting function like in Haskell
> with left bearing the error and right bearing the expected value but I
> wouldn't say that it replaces exception handling in Scala. I personally use
> either whenever I have a situation in which the reported error is an
> expected result and still use the exception mechanism whenever I want to
> report unexpected failure.
>
> -Stefan
>
> 2010/3/2 HHB
>>
>> Hey,
>> What is the advantages of Either ?
>> Is it the preferred Scala way to handle exception, so no more try catch?
>> I'm not clear about it.
>> Thanks for help and time.
>> --
>> View this message in context:
>> http://old.nabble.com/Why-and-when-to-use-Either--tp27753759p27753759.html
>> Sent from the Scala - User mailing list archive at Nabble.com.
>>
>
>

Ben Hutchison 3
Joined: 2009-11-02,
User offline. Last seen 42 years 45 weeks ago.
Re: Why and when to use Either?
On Tue, Mar 2, 2010 at 10:05 PM, Stefan Langer <mailtolanger [at] googlemail [dot] com> wrote:
 I personally use either whenever I have a situation in which the reported error is an expected result and still use the exception mechanism whenever I want to report unexpected failure.

I agree. Using Either acknowledges the possibility of error in the return type, but the tradeoff is more work handling the non-error case. Its appropriate for more frequent/expected error cases. Exceptions are untyped and they sit outside regular program control flow - they "break the rules". Use them for less frequent/expected error conditions, when the program itself has broken the rules.

-Ben



Detering Dirk
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
RE: Why and when to use Either?

> Exceptions are untyped [...]

Can you explain that statement a bit more?

As in my opinion a
x match { case e:Left[-some erased type-, B] => ... }

is far less typed than a
catch { case e:MyVeryOwnException => ... }

KR
Det

Chris Marshall
Joined: 2009-06-17,
User offline. Last seen 44 weeks 3 days ago.
RE: Why and when to use Either?
Either is particularly useful when parsing a large file (e.g. CSV) whereby each row represents either an instance of something, or some error. It can then be entirely up to the user what to do about these individual errors, but it would not make sense propagating an exception up the stack as the "normal" API behavour:

case class ParserError(val exception: Exception, var source: String, var lineNumber: Int)

trait RowDataParser[+A] {

  /**
   * Absract method to be filled in which should return one or more A's or throw a ParseException
   */
  @throws(classOf[ParseException])
  protected def parse(s: String): Iterable[A]


  /**
   * Returns a lazy iterator which encompasses the lines of the given source which have been either parsed
   * or encapsulated in a ParserError
   */
  def parse(source: Source): Iterator[Either[ParserError, A]] = {
    val ts: Iterable[A] = Nil
    source.getLines.zipWithIndex.flatMap[Either[ParserError, A]] { case (line, i) =>
        try {
          parse(line).elements map { a => Right(a) }
        }
        catch {
          case e: Exception => Iterator.single(Left(new ParserError(e, line, i)))
        }
    }
  }
}

Date: Tue, 2 Mar 2010 23:20:46 +1100
Subject: Re: [scala-user] Why and when to use Either?
From: brhutchison [at] gmail [dot] com
To: mailtolanger [at] googlemail [dot] com
CC: hubaghdadi [at] yahoo [dot] ca; scala-user [at] listes [dot] epfl [dot] ch

On Tue, Mar 2, 2010 at 10:05 PM, Stefan Langer <mailtolanger [at] googlemail [dot] com> wrote:
 I personally use either whenever I have a situation in which the reported error is an expected result and still use the exception mechanism whenever I want to report unexpected failure.

I agree. Using Either acknowledges the possibility of error in the return type, but the tradeoff is more work handling the non-error case. Its appropriate for more frequent/expected error cases. Exceptions are untyped and they sit outside regular program control flow - they "break the rules". Use them for less frequent/expected error conditions, when the program itself has broken the rules.

-Ben




We want to hear all your funny, exciting and crazy Hotmail stories. Tell us now
David Pollak
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
Re: Why and when to use Either?


On Tue, Mar 2, 2010 at 3:05 AM, Stefan Langer <mailtolanger [at] googlemail [dot] com> wrote:
It's the functional way of returning a value which can be one of two values. Further more it defines map, flatMap, filter and can therefor be used in for comprehensions.

The Either in Scala 2.7.7 and 2.8.0-BETA1 does not define map, flatMap, filter, or foreach.  Either cannot be used in a for comprehension.


 
It can be used as a error reporting function like in Haskell with left bearing the error and right bearing the expected value but I wouldn't say that it replaces exception handling in Scala. I personally use either whenever I have a situation in which the reported error is an expected result and still use the exception mechanism whenever I want to report unexpected failure.

-Stefan

2010/3/2 HHB <hubaghdadi [at] yahoo [dot] ca>

Hey,
What is the advantages of Either ?
Is it the preferred Scala way to handle exception, so no more try catch?
I'm not clear about it.
Thanks for help and time.
--
View this message in context: http://old.nabble.com/Why-and-when-to-use-Either--tp27753759p27753759.html
Sent from the Scala - User mailing list archive at Nabble.com.





--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics
Jason Zaugg
Joined: 2009-05-18,
User offline. Last seen 38 weeks 5 days ago.
Re: Why and when to use Either?

Actually, you can use Either in for comprehensions, after using .right
or .left to indicate which side you are interested in.

val a, b: Either[String, Int] = Right(1)
for { aa <- a.right
bb <- b.right
} yield aa + bb

As I mentioned earlier on the thread, scalaz.Validation designates one
type as the success type, and the other as the error, which removes a
little noise from usage in for comprehensions.

val a, b: Validation[String, Int] = 1.success
for { aa <- a
bb <- b
} yield aa + bb

-jason

On Tue, Mar 2, 2010 at 3:28 PM, David Pollak
wrote:

> The Either in Scala 2.7.7 and 2.8.0-BETA1 does not define map, flatMap,
> filter, or foreach.  Either cannot be used in a for comprehension.

David Pollak
Joined: 2008-12-16,
User offline. Last seen 42 years 45 weeks ago.
Re: Why and when to use Either?


On Tue, Mar 2, 2010 at 7:00 AM, Jason Zaugg <jzaugg [at] gmail [dot] com> wrote:
Actually, you can use Either in for comprehensions, after using .right
or .left to indicate which side you are interested in.

val a, b: Either[String, Int] = Right(1)
for { aa <- a.right
       bb <- b.right
} yield aa + bb


Thanks for the correction!
 

As I mentioned earlier on the thread, scalaz.Validation designates one
type as the success type, and the other as the error, which removes a
little noise from usage in for comprehensions.

val a, b: Validation[String, Int] = 1.success
for { aa <- a
       bb <- b
} yield aa + bb

-jason

On Tue, Mar 2, 2010 at 3:28 PM, David Pollak
<feeder [dot] of [dot] the [dot] bears [at] gmail [dot] com> wrote:

> The Either in Scala 2.7.7 and 2.8.0-BETA1 does not define map, flatMap,
> filter, or foreach.  Either cannot be used in a for comprehension.



--
Lift, the simply functional web framework http://liftweb.net
Beginning Scala http://www.apress.com/book/view/1430219890
Follow me: http://twitter.com/dpp
Surf the harmonics
Donna Malayeri
Joined: 2009-10-21,
User offline. Last seen 42 years 45 weeks ago.
Re: Why and when to use Either?
Sure, the type variables get erased in a pattern match (which may be changed at some point), but exceptions are not tracked by the type system and you can easily forget to handle something in the appropriate place. The pattern match approach forces you to deal with an error condition and is therefore giving you more static guarantees.

Donna

On Tue, Mar 2, 2010 at 2:03 PM, Detering Dirk <Dirk [dot] Detering [at] bitmarck [dot] de> wrote:
> Exceptions are untyped [...]

Can you explain that statement a bit more?

As in my opinion a
 x match {   case e:Left[-some erased type-, B] => ... }

is far less typed than a
 catch {  case e:MyVeryOwnException => ... }

KR
Det

James Iry
Joined: 2008-08-19,
User offline. Last seen 1 year 23 weeks ago.
Re: Why and when to use Either?
When somebody says "typed" they mean statically typed.

If x is statically typed as an Either then type erasure doesn't come into play. 

scala> def foo(x : Either[String, Int]) = x match {case Left(s) => s.length; case Right(n) => 27 * n}

scala> foo(Left("hello"))
res1: Int = 5

scala> foo(Right(3))
res2: Int = 81

scala> foo(Left(3))
<console>:7: error: type mismatch;
 found   : Int(3)
 required: String
       foo(Left(3))

In Java, checked exceptions have a static typing. Scala ditches that entirely.

On Tue, Mar 2, 2010 at 5:03 AM, Detering Dirk <Dirk [dot] Detering [at] bitmarck [dot] de> wrote:
> Exceptions are untyped [...]

Can you explain that statement a bit more?

As in my opinion a
 x match {   case e:Left[-some erased type-, B] => ... }

is far less typed than a
 catch {  case e:MyVeryOwnException => ... }

KR
Det

Stefan Langer
Joined: 2009-10-23,
User offline. Last seen 42 years 45 weeks ago.
Re: Why and when to use Either?


2010/3/2 James Iry <jamesiry [at] gmail [dot] com>
In Java, checked exceptions have a static typing. Scala ditches that entirely.
Could you elaborate some more on this? Cause I do not see how Scala can consider RuntimeException and IllegalStateException to be of the same type.
Are you referring to the way Scala handles exception using pattern matching?

I'm confused...
Donna Malayeri
Joined: 2009-10-21,
User offline. Last seen 42 years 45 weeks ago.
Re: Why and when to use Either?
On Wed, Mar 3, 2010 at 10:11 AM, Stefan Langer <mailtolanger [at] googlemail [dot] com> wrote:


2010/3/2 James Iry <jamesiry [at] gmail [dot] com>
In Java, checked exceptions have a static typing. Scala ditches that entirely.
Could you elaborate some more on this? Cause I do not see how Scala can consider RuntimeException and IllegalStateException to be of the same type.
Are you referring to the way Scala handles exception using pattern matching?

I'm confused...

He means that exceptions thrown by a method are tracked by the Java type system, but not in Scala. So, in Scala, any method can throw any exception (runtime exception or otherwise) without there needing to be an annotation on the method. This is different from exception classes themselves having different types.

Donna
James Iry
Joined: 2008-08-19,
User offline. Last seen 1 year 23 weeks ago.
Re: Why and when to use Either?
RuntimeException and IllegalStateException are indeed different types.  But when they are thrown as exceptions Scala does not statically track the type.  But neither does Java since neither are checked.

Here's some Java using checked exceptions to illustrate the point...

class MyException1 extends Exception{};
class MyException2 extends Exception{};

public void foo() throws MyException1 {throw new MyException2();} // static type error!

Java also has a rich set of checked exception rules regarding interface implementation and method overriding.

Scala ditches all that because, in the end, Java's checked exceptions proved to be too painful to use especially in "generic" code.   Perhaps someday we'll see that kind of effect typing in a more convenient to use package.

On Wed, Mar 3, 2010 at 1:11 AM, Stefan Langer <mailtolanger [at] googlemail [dot] com> wrote:


2010/3/2 James Iry <jamesiry [at] gmail [dot] com>
In Java, checked exceptions have a static typing. Scala ditches that entirely.
Could you elaborate some more on this? Cause I do not see how Scala can consider RuntimeException and IllegalStateException to be of the same type.
Are you referring to the way Scala handles exception using pattern matching?

I'm confused...

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland