Вы можете думать о R => Either[L, B]
как о «обобщенном значении типа L
» - это не совсем то же самое, что и L
, но с учетом R
это может привести к L
. Итак, ваш flatMap
"использует обобщенные значения типа L
". В то же время ваша декларация отклонений утверждает, что Either[+L, +R]
является ковариантным в L
, поэтому Either[VerySpecial, R]
должен быть частным случаем Either[RatherGeneral, R]
. Но это невозможно, потому что flatMap
, который может потреблять только значения VerySpecial
, будет подавлен на входе RatherGeneral
.
- В
Either[+L, +R]
, L
находится в ковариантном положении (он "производит" L
с, по крайней мере иногда)
- В
R => Either[L, B]
, L
все еще находится в ковариантном положении (потому что функция производит Either[L, B]
, а Either[L, B]
в свою очередь производит L
с, поэтому все это производит L
с)
- В
(R => Either[L, B]) => Either[L, B]
первый L
появляется в против вариант позиции, потому что часть аргумента потребляется по методу flatMap
.
Это легко исправить с помощью стандартного трюка с ограничением типа:
sealed trait Either[+L, +R] {
def flatMap[B, M >: L](f: R => Either[M, B]): Either[M, B] = this match {
case Left(e) => Left(e)
case Right(e) => f(e)
}
}
final case class Right[+A, +B](right: B) extends Either[A, B]
final case class Left[+A, +B](left: A) extends Either[A, B]