I am not sure semantics are entirely isomorphic between Try[A]
and Either[Throwable, A]
. For example, we can change the bias of Either
val e: Either[Throwable, Int] = Left(new Exception("boom"))
for (s <- e.left) yield s.getMessage.length
res5: scala.util.Either[Int,Int] = Left(4)
or swap the sides
e.swap
res6: scala.util.Either[Int,Throwable] = Right(java.lang.Exception: boom)
Consider some unusual scenario where we consider Throwable
s to actually be the expected result and hence would want them on the Right
side. Perhaps we are building some pure-functional testing library where we want to provide an API for asserting on exceptions. One could imagine encoding these semantics as Either[A, Throwable]
.
Another potential advantage of Either
over Try
might be cats providing more extension methods for it. For example, consider all the goodies in import cats.syntax.either._
whilst I am not aware of similar for Try
. Say we want to accumulate all the errors in a list instead of short-circuit, then we can simply traverse(_.toValidatedNec)
like so
import cats.syntax.either._
import cats.instances.list._
import cats.syntax.traverse._
val l: List[Either[Throwable, Int]] = List(Right(1), Right(2), Left(new RuntimeException("boom")), Right(3), Left(new RuntimeException("crash")))
l.traverse(_.toValidatedNec)
res0: cats.data.ValidatedNec[Throwable,List[Int]] = Invalid(Chain(java.lang.RuntimeException: boom, java.lang.RuntimeException: crash))
To achieve similar with Try
I think we would have to work harder.