getOrElse Signatures for a LeftProjection[A, B] :
def getOrElse[AA >: A](or: ⇒ AA): AA
i.e. he expects the argument to have some type AA , which is a supertype of A
In the first example, you left type annotations, allowing the compiler to output Nothing for A Then you provided an argument of type LeftProjection[Nothing, Int] .
Since Nothing is a subtype of all types, LeftProjection[Nothing, Int] trivially a supertype! This special case in the type system means that he checked the type almost by accident.
However, the most specific common supertype of String and LeftProjection[String, Int] is Serializable .
So, if you want to bind Either s, you need a method that can take another Either[A, B] , not just 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 }
(Similarly, you can write rightOrElse , which is a more common use case.)
This becomes syntactically more convenient 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 }
Since this expects Either[A, B] for both operands instead of A or B (or some supertype), you can link your Either s.
scala> Right[String, Int](2) leftOrElse Right[String, Int](4) leftOrElse Left[String, Int]("Error") res1: Either[String,Int] = Left(Error)