问题
I am trying to understand why the following piece of code won't compile when I use a higher kinded type parameter for T in MyModel
abstract class Model[M <: Model[M]]
class MyModel[T] extends Model[MyModel[T]]
class Bar[TModel <: Model[TModel]]
object Foo extends App {
new Bar[MyModel[_]]
}
But if i change it to new Bar[MyModel[Any]]
it will compile. Why is this ?
回答1:
Bar[MyModel[_]]
is Bar[MyModel[X] forSome {type X}]
.
(It should not be confused neither with Bar[MyModel[X]] forSome {type X}
nor with Bar[MyModel[X forSome {type X}]]
, the latter is just Bar[MyModel[Any]]
. These are three different types.)
Bar[MyModel[X] forSome {type X}]
(aka Bar[MyModel[_]]
) doesn't compile because MyModel[X] forSome {type X}
(aka MyModel[_]
) doesn't satisfy Bar
's condition TModel <: Model[TModel]
. Indeed you can check that
implicitly[(MyModel[X] forSome {type X}) <:< Model[MyModel[X] forSome {type X}]]
doesn't compile (X
to the left from <:<
and X
to the right from <:<
are not related). The thing is that skolemization of existential type on the left MyModel[X] forSome {type X}
, namely MyModel[X1]
is not connected to Model[MyModel[X] forSome {type X}]
on the right, for invariant Model
(from class MyModel[T] extends Model[MyModel[T]]
it follows that MyModel[X1] <: Model[MyModel[X1]]
(1), also MyModel[X1] <: (MyModel[X] forSome {type X})
(2), but for invariant Model
we can't apply Model
to the latter "inequality").
But if you make Model
covariant abstract class Model[+M <: Model[M]]
then we can apply Model
to "inequality" (2), so Model[MyModel[X1]] <: Model[MyModel[X] forSome {type X}]
and this along with (1) gives MyModel[X1] <: Model[MyModel[X] forSome {type X}]
by transitivity. So Bar
's condition is satisfied and new Bar[MyModel[_]]
compiles.
Bar[MyModel[Any]]
compiles because MyModel[Any]
satisfies Bar
's condition TModel <: Model[TModel]
. Indeed MyModel[Any] <: Model[MyModel[Any]]
because class MyModel[T] extends Model[MyModel[T]]
(you can check that
implicitly[MyModel[Any] <:< Model[MyModel[Any]]]
compiles).
来源:https://stackoverflow.com/questions/61701021/understanding-type-arguments-do-not-conform-to-class-type-parameter-bounds-error