If Either
, Left
, Right
were invariant the following code would compile
trait Either[E, A] {
def map[B](f: A => B): Either[E, B] =
this match {
case Right(a) => Right(f(a))
case Left(e) => Left(e)
}
def flatMap[B](f: A => Either[E, B]): Either[E, B] =
this match {
case Left(e) => Left(e)
case Right(a) => f(a)
}
def orElse(b: => Either[E, A]): Either[E, A] =
this match {
case Left(_) => b
case Right(a) => Right(a)
}
def map2[B, C](b: Either[E, B])(f: (A, B) => C): Either[E, C] =
for { a <- this; b1 <- b } yield f(a,b1)
}
case class Left[E, A](value: E) extends Either[E, A]
case class Right[E, A](value: A) extends Either[E, A]
If you now make Either
, Left
, Right
covariant this code start not to compile with covariant type occurs in contravariant position
. One fix is to introduce EE >: E
, AA >: A
where necessary. Another possible fix would be to define map
, flatMap
, orElse
, map2
as extension methods like it’s done in Shapeless with HList
methods to avoid covariance issues.