Either to Try and vice versa in Scala
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)
}
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)
}
}
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))
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]