Why when I type this all works fine?
Right(2).left getOrElse Right(4).left getOrElse Left("Error")
but when I type this compilation fails?
Right[String, Int](2).left getOrElse Right[String, Int](4).left getOrElse Left[String, Int]("Error")
Compilation error:
value getOrElse is not a member of java.io.Serializable
println(RightString, Int.left getOrElse RightString, Int.left getOrElse LeftString, Int)
So I can't chain getOrElse method call
The signature of getOrElse for a LeftProjection[A, B] is:
def getOrElse[AA >: A](or: ⇒ AA): AA
i.e. it expects the argument to be of some type AA which is a supertype of A.
In the first example, you left out type annotations, allowing the compiler to infer Nothing for A. Then, you supplied an argument of type LeftProjection[Nothing, Int].
Because Nothing is a subtype of all types, LeftProjection[Nothing, Int] is trivially a supertype! This special case in the type system means that it type-checked almost by accident.
However, the most specific common supertype of String and LeftProjection[String, Int] is Serializable.
So, if you want to chain Eithers, you need a method which can take another Either[A, B], not just an A or B.
The method you seem to want would look like this:
def leftOrElse[A, B](e1: Either[A, B], e2: => Either[A, B]): Either[A,B] =
e1 match {
case Left(a) => Left(a)
case Right(b) => e2
}
(You could similarly write rightOrElse, which is a more common use case.)
This becomes syntactically a bit more usable if you make it an extension method, using implicits.
implicit class EitherOps[A, B](e1: Either[A, B]) {
def leftOrElse(e2: => Either[A, B]): Either[A,B] = // as above
}
Because this expects Either[A, B] for both operands, instead of A or B (or some supertype thereof), you can chain your Eithers.
scala> Right[String, Int](2) leftOrElse Right[String, Int](4) leftOrElse Left[String, Int]("Error")
res1: Either[String,Int] = Left(Error)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With