Bar[MyModel[_]]
равно Bar[MyModel[X] forSome {type X}]
.
(Его не следует путать ни с Bar[MyModel[X]] forSome {type X}
, ни с Bar[MyModel[X forSome {type X}]]
, последнее просто Bar[MyModel[Any]]
. Это три разных типа.)
Bar[MyModel[X] forSome {type X}]
(он же Bar[MyModel[_]]
) не компилируется, потому что MyModel[X] forSome {type X}
(он же MyModel[_]
) не удовлетворяет условию Bar
TModel <: Model[TModel]
. Действительно, вы можете проверить, что
implicitly[(MyModel[X] forSome {type X}) <:< Model[MyModel[X] forSome {type X}]]
не компилируется (X
слева от <:<
и X
справа от <:<
не связаны). Дело в , что сколемизация экзистенциального типа слева MyModel[X] forSome {type X}
, а именно MyModel[X1]
не связана с Model[MyModel[X] forSome {type X}]
справа, для инварианта Model
(от class MyModel[T] extends Model[MyModel[T]]
следует, что MyModel[X1] <: Model[MyModel[X1]]
(1), также MyModel[X1] <: (MyModel[X] forSome {type X})
(2), но для инварианта Model
мы не можем применить Model
к последнему «неравенству»).
Но если вы делаете Model
ковариантным abstract class Model[+M <: Model[M]]
, тогда мы можем применить Model
к «неравенству» (2), поэтому Model[MyModel[X1]] <: Model[MyModel[X] forSome {type X}]
и это вместе с (1) дает MyModel[X1] <: Model[MyModel[X] forSome {type X}]
по транзитивности. Итак, условие Bar
выполнено, и new Bar[MyModel[_]]
компилируется.
Bar[MyModel[Any]]
компилируется, потому что MyModel[Any]
удовлетворяет Bar
условию TModel <: Model[TModel]
. Действительно MyModel[Any] <: Model[MyModel[Any]]
, потому что class MyModel[T] extends Model[MyModel[T]]
(вы можете проверить, что
implicitly[MyModel[Any] <:< Model[MyModel[Any]]]
компилируется).