Подтвердить что ты не робот

Невозможно вывести контравариантный параметр Ничего типа

Рассмотрим следующий фрагмент:

trait X[-T]
object Y extends X[Nothing]
def a[T](x: X[T]): X[T] = x
a(Y)

Компиляция вышеизложенного (2.12.3) не выполняется:

type mismatch;
found   : Y.type
required: X[T]
   a(Y)
     ^

Это компилируется отлично, если:

  • используется другой тип, чем Nothing (например, object Y extends X[String])
  • метод a не использует T в своем возвращаемом типе (например, def a[T](x: X[T]): Unit = {})
  • параметр типа для a явно задан (т.е. a[Nothing](Y))
  • T является ковариантным, а не контравариантным (также терпит неудачу, если он инвариантен)

Это какой-то особый случай в компиляторе для Nothing?

Как "интересная" работа, кажется, что все работает нормально:

trait X[-T]
object Y extends X[Nothing]
def a[T, U <: T](x: X[T]): X[U] = x
a(Y)
4b9b3361

Ответ 1

Я попытаюсь объяснить строку кода строкой

Строка 1: trait X[-T] → признак X контравариантен в типе Т. Таким образом, вы можете заменить любую переменную типа X [T] своим подтипом. В случае контравариантных типов Z [A] является подтипом Z [B], если B является подтипом A.

Строка 2: object Y extends X[Nothing] → объект Y имеет тип X [Nothing]. Обратите внимание: ничто не является подтипом всех других типов.

Строка 3: def a[T](x: X[T]): X[T] = x → определить выражение, которое принимает аргументы типа X [T]. Поскольку признак X контравариантен в типе T, вы также можете передавать подтипы X [T], то есть X [N], такие, что T является подтипом N

Строка 4: a(Y) → Вызвать выражение 'a' с аргументом типа X [Nothing]. Поскольку компилятор не знает тип аргумента 'a', он не может решить, является ли X [Nothing] подтипом X [T]. Существует несколько способов решения этой проблемы.

Solution 1: `a[Nothing]` -> explicitly defining the type

Solution 2: `tait X[+T]` -> make X covariant in type T. In this case Z[A] is subtype of Z[B] if A is subtype of B. This will work because Nothing is subtype of any other type