Невозможно вывести контравариантный параметр типа 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