The compiler is telling me this can't be with a warning of: "contravariant type A occurs in covariant position in type >: A <: Any of type B." The warning is in the type parameter of the compose method. Logically the type definition makes sense to me. If the compiler has no qualms with andThen, why the problem with the converse?
trait Foo[-A]{
def compose[B >: A](t: Foo[B]): Foo[A] = t andThen this
def andThen[B <: A](t: Foo[B]): Foo[B]
}
All I need is an example where it breaks down. Then I'm happy.
Covariance is a concept that is very straightforward to understand. We say that a type constructor F[_] is covariant if B is a subtype of type A and F[B] is a subtype of type F[A]. In Scala, we declare a covariant type constructor using the notation F[+T], adding a plus sign on the left of the type variable.
Covariance allows assigning an instance to a variable whose type is one of the instance's generic type; i.e. supertype. Contravariance allows assigning an instance to a variable whose type is one of the instance's derived type; i.e. subtype.
The Scala standard library has a generic immutable sealed abstract class List[+A] class, where the type parameter A is covariant. This means that a List[Cat] is a List[Animal] .
As the error says, your variance annotation of A
is wrong. You cannot use A
in a return type which is a covariant position. Imagine you had another method in Foo
which uses A
in proper contravariant position (as an argument):
trait Foo[-A] {
...
def foo(a: A): Unit
}
Now you can see how this crashes:
Foo[-A]
implies that Foo[X] <: Foo[Y]
if X >: Y
-A
was legal here, compose
might return a Foo[A1]
for some A1 >: A
trait X
and trait Y extends X { def bar() }
Foo[Y]
where foo
calls a.bar()
compose
was allowed to return Foo[X]
So for you example to compile, A
must be invariant.
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