Подпись getOrElse
для LeftProjection[A, B]
:
def getOrElse[AA >: A](or: ⇒ AA): AA
то есть он ожидает, что аргумент будет иметь некоторый тип AA
, который является супертипом A
.
В первом примере вы пропустили аннотации типов, что позволило компилятору вывести Nothing
вместо A
. Затем вы предоставили аргумент типа LeftProjection[Nothing, Int]
.
Поскольку Nothing
является подтипом всех типов, LeftProjection[Nothing, Int]
тривиально является супертипом! Этот особый случай в системе типов означает, что она проверяет тип почти случайно.
Однако наиболее специфичным общим супертипом String
и LeftProjection[String, Int]
является Serializable
.
Итак, если вы хотите связать Either
, вам нужен метод, который может принимать еще Either[A, B]
, а не только A
или B
.
Метод, который вы, кажется, хотите, будет выглядеть так:
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
}
(Аналогичным образом вы можете написать rightOrElse
, что является более распространенным вариантом использования.)
Это становится синтаксически немного более удобным, если вы сделаете его методом расширения, используя имплициты.
implicit class EitherOps[A, B](e1: Either[A, B]) {
def leftOrElse(e2: => Either[A, B]): Either[A,B] = // as above
}
Поскольку это предполагает Either[A, B]
для обоих операндов вместо A
или B
(или какого-то их супертипа), вы можете связать свои Either
s.
scala> Right[String, Int](2) leftOrElse Right[String, Int](4) leftOrElse Left[String, Int]("Error")
res1: Either[String,Int] = Left(Error)
person
Ben James
schedule
21.08.2013