为什么 Scala 在泛型函数类型参数推断中无法将 Null 类型识别为 T 的子类型?
Why Scala fail to recognize Null type as a subtype of T in generic function type parameter inference?
我在 Scala 中有以下函数定义:
trait GenExtractor[+R] P
def orElseExtractor[R2<: Super, Super>: R](g: GenExtractor[T, R2]): GenExtractor[T, Super] =
new OrElse[T, Super](this, g)
}
应该组合 2 个 GenExtractor:
GenExtractor[A]
GenExtractor[B]
进入:
GenExtractor[C]
其中 C 是 A 和 B 的公共超类型
但是,当我尝试调用此函数时:
val genExtractor = new GenExtractor[R](...parameters...)
val combined = genExtractor.orElseExtractor[Null, R] {
_: FetchedRow => null
}
我收到以下错误:
Error:(84, 47) type arguments [Null,R] do not conform to method orElseExtractor's type parameter bounds [R2 <: Super,Super >: R]
def orNull: Extractor[R] = orElseExtractor[Null, R] {
^
这显然是误报,因为在这种情况下:
type R2 = Null
type Super = R
满足条件:Null<:R&R>:R
为什么 scala 编译器给我这个错误?我应该怎么做才能解决它?
为什么 Null
是泛型 R
的子类型?这不是编译器偏离了目标,而是 Null <: R
始终为真的基本假设。这里有一些有趣的例子,它们与基元有关。
Some(5).orNull
将产生 error: Cannot prove that Null <:< Int
这是你的差距,你可以在 REPL 中尝试一下:
implicitly[Null <:< AnyRef] // will compile
implicitly[Null <:< AnyVal] // blows up, primitives are not included.
在类型系统中,所有类型的超类型,唯一保证满足您期望的任何此类关系的是scala.Nothing
,而不是scala.Null
。
null
JVM 上的设计主要是为了应对类型信息的缺失,而不是为了处理类型系统层次结构。为此,您有 Nothing
、AnyRef
、AnyVal
和所有其他有趣的东西。
我在 Scala 中有以下函数定义:
trait GenExtractor[+R] P
def orElseExtractor[R2<: Super, Super>: R](g: GenExtractor[T, R2]): GenExtractor[T, Super] =
new OrElse[T, Super](this, g)
}
应该组合 2 个 GenExtractor:
GenExtractor[A]
GenExtractor[B]
进入:
GenExtractor[C]
其中 C 是 A 和 B 的公共超类型
但是,当我尝试调用此函数时:
val genExtractor = new GenExtractor[R](...parameters...)
val combined = genExtractor.orElseExtractor[Null, R] {
_: FetchedRow => null
}
我收到以下错误:
Error:(84, 47) type arguments [Null,R] do not conform to method orElseExtractor's type parameter bounds [R2 <: Super,Super >: R]
def orNull: Extractor[R] = orElseExtractor[Null, R] {
^
这显然是误报,因为在这种情况下:
type R2 = Null
type Super = R
满足条件:Null<:R&R>:R
为什么 scala 编译器给我这个错误?我应该怎么做才能解决它?
为什么 Null
是泛型 R
的子类型?这不是编译器偏离了目标,而是 Null <: R
始终为真的基本假设。这里有一些有趣的例子,它们与基元有关。
Some(5).orNull
将产生 error: Cannot prove that Null <:< Int
这是你的差距,你可以在 REPL 中尝试一下:
implicitly[Null <:< AnyRef] // will compile
implicitly[Null <:< AnyVal] // blows up, primitives are not included.
在类型系统中,所有类型的超类型,唯一保证满足您期望的任何此类关系的是scala.Nothing
,而不是scala.Null
。
null
JVM 上的设计主要是为了应对类型信息的缺失,而不是为了处理类型系统层次结构。为此,您有 Nothing
、AnyRef
、AnyVal
和所有其他有趣的东西。