Дано:Разрешение на вариант [ничего]?
scala> def f[F[_], A, B](x: F[A], y: F[B]): F[B] = y
f: [F[_], A, B](x: F[A], y: F[B])F[B]
Как тип выхода из ниже вызова вычисляться Option[Nothing]
?
scala> :t f(Option(42), ???)
Option[Nothing]
Дано:Разрешение на вариант [ничего]?
scala> def f[F[_], A, B](x: F[A], y: F[B]): F[B] = y
f: [F[_], A, B](x: F[A], y: F[B])F[B]
Как тип выхода из ниже вызова вычисляться Option[Nothing]
?
scala> :t f(Option(42), ???)
Option[Nothing]
Смотрите определение ???:
def ??? : Nothing = throw new NotImplementedError
Так F
является Option
и B
является Nothing
, таким образом, ваше возвращение тип Option[Nothing]
.
https://www.scala-lang.org/files/archive/spec/2.12/03-types.html#conformance Эта часть спецификации особенно полезна здесь.
Возьмите функцию:
scala> def f[F[_], A, B >: Nothing <: Any](fa: F[A], fb: F[B]): F[B] = fb
f: [F[_], A, B](fa: F[A], fb: F[B])F[B]
Компилятор видит это как (более или менее):
scala> def fAnnotated[F[_], A >: Nothing <: Any, B >: Nothing <: Any](fa: F[A], fb: F[B]): F[B] = fb
fAnnotated: [F[_], A, B](fa: F[A], fb: F[B])F[B]
Таким образом, компилятор делает вывод, что ваши типы имеют нижнюю границу Ничто и верхняя . Мы можем видеть это в действии с вашим примером.
scala> :t f(Option(42), ???)
Option[Nothing]
И с контравариантного типа CTOR Любой выводится:
scala> trait T[-A]
defined trait T
scala> :t f(new T[Int]{}, ???)
T[Any]
Скала компилятор ищет наиболее ограничительный вариант типа, где разумность держит хорошо. Поскольку он не может найти B (на самом деле нет такой вещи, как B), он ничего не знает для инвариантных и ковариантных случаев и Any для контравариантного случая.
Я не уверен, что это действительно объясняет, почему 'B' считается« Ничто ». Как вы получаете от выражения '???' к типу 'Option [Nothing]' требуется еще несколько шагов. –
Я думаю, что это побочный эффект того, как компилятор пытается подобрать конструкторы типов в иерархии типов между 'Any' и' Nothing'. –
'F [B]' фактически 'Nothing', но' Nothing' также является 'Option [Nothing]', что, безусловно, помогает компилятору найти наименьшую верхнюю границу 'Option' для' F'. –