I covered the relationship between Try
, Either
, and Option
in this answer. The highlights from there regarding the relationship between Try
and Either
are summarized below:
Try[A]
is isomorphic to Either[Throwable, A]
. In other words you can treat a Try
as an Either
with a left type of Throwable
, and you can treat any Either
that has a left type of Throwable
as a Try
. It is conventional to use Left
for failures and Right
for successes.
Of course, you can also use Either
more broadly, not only in situations with missing or exceptional values. There are other situations where Either
can help express the semantics of a simple union type (where value is one of two types).
Semantically, you might use Try
to indicate that the operation might fail. You might similarly use Either
in such a situation, especially if your "error" type is something other than Throwable
(e.g. Either[ErrorType, SuccessType]
). And then you might also use Either
when you are operating over a union type (e.g. Either[PossibleType1, PossibleType2]
).
The standard library does not include the conversions from Either
to Try
or from Try
to Either
, but it is pretty simple to enrich Try
, and Either
as needed:
object TryEitherConversions {
implicit class EitherToTry[L <: Throwable, R](val e: Either[L, R]) extends AnyVal {
def toTry: Try[R] = e.fold(Failure(_), Success(_))
}
implicit class TryToEither[T](val t: Try[T]) extends AnyVal {
def toEither: Either[Throwable, T] = t.map(Right(_)).recover(PartialFunction(Left(_))).get
}
}
This would allow you to do:
import TryEitherConversions._
//Try to Either
Try(1).toEither //Either[Throwable, Int] = Right(1)
Try("foo".toInt).toEither //Either[Throwable, Int] = Left(java.lang.NumberFormatException)
//Either to Try
Right[Throwable, Int](1).toTry //Success(1)
Left[Throwable, Int](new Exception).toTry //Failure(java.lang.Exception)
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…