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

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

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)

1 ответ

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

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

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

Строка 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
Другие вопросы по тегам