Either to Try and vice versa in Scala
Asked Answered
D

5

29

Are there any conversions from Either to Try and vice versa in the Scala standard library ? Maybe I am missing something but I did not find them.

Dinosaurian answered 20/3, 2014 at 12:1 Comment(0)
C
21

(NOTICE: this answer applies to Scala 2.11. for more recent versions of Scala, see other answers)

To the best of my knowledge this does not exist in the standard library. Although an Either is typically used with the Left being a failure and the Right being a success, it was really designed to support the concept of two possible return types with one not necessarily being a failure case. I'm guessing these conversions that one would expect to exist do not exist because Either was not really designed to be a Success/Fail monad like Try is. Having said that it would be pretty easy to enrich Either yourself and add these conversions. That could look something like this:

object MyExtensions {
  implicit class RichEither[L <: Throwable,R](e:Either[L,R]){
    def toTry:Try[R] = e.fold(Failure(_), Success(_))
  }
  
  implicit class RichTry[T](t:Try[T]){
    def toEither:Either[Throwable,T] = t.transform(s => Success(Right(s)), f => Success(Left(f))).get
  }  
}

object ExtensionsExample extends App{
  import MyExtensions._
  
  val t:Try[String] = Success("foo")
  println(t.toEither)
  val t2:Try[String] = Failure(new RuntimeException("bar"))
  println(t2.toEither)
  
  val e:Either[Throwable,String] = Right("foo")
  println(e.toTry)
  val e2:Either[Throwable,String] = Left(new RuntimeException("bar"))
  println(e2.toTry)
}
Contrecoup answered 20/3, 2014 at 12:32 Comment(1)
While this is a great solution, as of 2018 toTry and toEither are included in scala 2.12. It's probably worth adding an edit to the top of you answer.Eserine
C
16

In Scala 2.12.x Try has a toEither method: http://www.scala-lang.org/api/2.12.x/scala/util/Try.html#toEither:scala.util.Either[Throwable,T]

Campanile answered 25/12, 2016 at 17:38 Comment(1)
2.12 also has an Either.toTry method scala-lang.org/api/2.12.0/scala/util/…Reticulum
D
15
import scala.util.{ Either, Failure, Left, Right, Success, Try }

implicit def eitherToTry[A <: Exception, B](either: Either[A, B]): Try[B] = {
  either match {
    case Right(obj) => Success(obj)
    case Left(err) => Failure(err)

  }
}
implicit def tryToEither[A](obj: Try[A]): Either[Throwable, A] = {
  obj match {
    case Success(something) => Right(something)
    case Failure(err) => Left(err)
  }
}
Dissuasion answered 20/3, 2014 at 12:36 Comment(2)
Why are you throwing the error and the catching it with Try instead of just wrapping with Failure?Piane
+1 for clear code & pattern matching compared to the other answer.Bentwood
J
7

The answer depends on how to convert the Failure to Left (and vice versa). If you don't need to use the details of the exception, then Try can be converted to Either by going the intermediate route of an Option:

val tried = Try(1 / 0)
val either = tried.toOption.toRight("arithmetic error")

The conversion the other way requires you to construct some Throwable. It could be done like this:

either.fold(left => Failure(new Exception(left)), right => Success(right))
Joscelin answered 28/10, 2016 at 4:54 Comment(0)
S
1

As of Scala 2.13 (and hence Scala 3) the standard library supports both conversions. The conversion from Either to Try in the Scala standard library is documented here, and vice versa is documented here.

Serow answered 3/12, 2023 at 18:42 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.