Why does the Scala compiler say that contravariant type A occurs in a covariant position in type>: A <: Any of type B?

The compiler tells me that this cannot be with a warning: "contravariant type A occurs in a covariant position in type>: A <: Any of type B." The warning is in the type parameter of the layout method. Logically, type definition makes sense to me. If the compiler has no confusion with andThen, why the problem with the reverse?

 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. Then I am happy.

+6
source share
1 answer

As the error says, your rejection annotation A is incorrect. You cannot use A in the return type, which is a covariant position. Imagine you had another method in Foo that uses A in the right contravariant position (as an argument):

 trait Foo[-A] { ... def foo(a: A): Unit } 

Now you can see how this happens:

  • Foo[-A] means that Foo[X] <: Foo[Y] if X >: Y
  • the return value may be a subtype of the declared return type
  • therefore, if -A is legal here, compose can return Foo[A1] for some A1 >: A
  • say trait X and trait Y extends X { def bar() }
  • imagine Foo[Y] where Foo calls a.bar()
  • therefore, it will break if compose allowed to return Foo[X]

So, for an example to compile, A must be invariant.

+4
source

All Articles