In Scala, is the transitive rule of covariance missing?

58 Views Asked by At

E.g.

  trait AA[+X[n], +Y] {

    def x: X[Y] // [Error]: covariant type Y occurs in invariant position in type => X[Y] of method x
  }

This appears to be the wrong message, as X[Y] can be easily proven to be covariant:

if Y1 >:> Y2, +X1[n] >:> +X2[n] for all n, then:

Y1 >:> Y2

(covariance of X2) => X2[Y1] >:> X2[Y2]

(X1[Y1] >:> X2[Y1]) => X1[Y1] >:> X2[Y2]

What may have caused this error message?

1

There are 1 best solutions below

1
Dmytro Mitin On BEST ANSWER

You are missing one more +. Correct is

trait AA[+X[+n], +Y] {
  def x: X[Y]
}

Then the type X will be covariant (with respect to its type parameter n) and the position

  def x: X[...]
//         ^^^  <- this position

will be covariant and you'll be able to use covariant type parameter Y at this position.

On contrary, you declared invariant type X (w.r.t. n) and tried to use covariant type parameter Y at an invariant position.

There are different notions:

+X[n] is a covariant type parameter of AA but invariant type with respect to its type parameter n.

The following conclusion was incorrect:

(covariance of X2) => X2[Y1] >:> X2[Y2]

Also correct would be to make Y invariant

trait AA[+X[n], Y] {
  def x: X[Y]
}

By the way, yesterday Oleg Nizhnikov (@odomontois) had a training on variances (among other topics) https://youtu.be/l08tK1x89ho?t=7494 (starting from 2:04:54).