Option 类型的子类型关系
Subtype relation of Option type
最近了解了一点scala的子类型系统,对Option
类型和它的子类型之间的关系很好奇。我了解到以下陈述是正确的。
if A <: B, then (A => C) >: (B => C)
此外,我了解到 A <: B
意味着存在一些 B
的实例,但不能是 A
的实例。如果我将这些应用到 Option
类型,那么我会得到以下结果。为方便起见,我将跳过 ⱯA.
符号。
Nothing
<: Option[A]
, 所以 Option[A] => string
<: Nothing => string
- 我想不出任何
Nothing => string
的实例不是 Option[A] => string
的实例,所以 Nothing => string
<: Option[A] => string
Nothing => string
(<: 和>:) Option[A] => string
,因此 Nothing => string
在子类型 中实际上等于 Option[A] => string
Option[A] => string
<: Some[A] => string
, 所以 Nothing => string
<: Some[A] => string
Some[A]
<: Nothing
由于我强烈怀疑结果是否正确,我认为中间出了问题。谁能解释一下这里发生了什么?
我会简单地拆开每一步。
Nothing
不接受任何类型参数。您可能是指 None
,它属于 None.type
类型,而后者又是 Option[Nothing]
.
- 为什么不呢?
-
def foo(n: None.type): String = "blah"
println(foo(None)) // ok
// println(foo(Some("string"))) // doesn't compile.
- 错误。
- 原则上传递性正确,但前一步错误
- 错误,因为之前的步骤错误。为什么这个推理应该普遍成立尚不完全清楚。
所以,没有。现在你可以想到一个接受 None
而不是一般 Option
.
的函数
注:None.type
是单例对象的类型None
。一般来说,单例对象的类型Obj
是Obj.type
.
我认为你混淆了一些东西。我认为A -> B
应该是A => B
,一个从A
到B
的函数。接下来, Nothing[A]
不存在,只有 Nothing
是 Scala 中的底层类型(sub-type 所有类型)。但你可能指的是对象 None
(类型为 None.type
),它是 Option
的 sub-type。
那么你的第一个假设是正确的:
implicitly[None.type <:< Option[_]] // ok
implicitly[(Option[_] => String) <:< (None.type => String)] // ok
我改写你的第二个假设:
I cannot think of any instance of None.type => String
that is not an instance of Option[A] => String
, so (None.type => String) <: (Option[A] => String)
这个假设是错误的:
implicitly[(None.type => String) <:< (Option[_] => String)]
error: Cannot prove that None.type => String <:< Option[_] => String.
implicitly[(None.type => String) <:< (Option[_] => String)]
^
可能很难想象,因为None
不会添加任何不属于Option
接口的方法。但以一般动物(如Option
)和特殊动物(如None
)为例
trait Animal // aka Option
object Dog extends Animal { def bark() = "bark!" }
object Cat extends Animal { def purr() = "purr!" } // aka None
你的第二个假设意味着 (Cat => String) <: (Animal => String)
。如果为真,则可能出现以下情况:
val fun: Animal => String = { c: Cat.type => c.purr } // doesn't compile
让我们强制:
val fun: Animal => String = { c: Cat.type => c.purr } .asInstanceOf[Animal => String]
fun(Dog) // try run this
java.lang.ClassCastException: Dog$ cannot be cast to Cat$
... 64 elided
最近了解了一点scala的子类型系统,对Option
类型和它的子类型之间的关系很好奇。我了解到以下陈述是正确的。
if A <: B, then (A => C) >: (B => C)
此外,我了解到 A <: B
意味着存在一些 B
的实例,但不能是 A
的实例。如果我将这些应用到 Option
类型,那么我会得到以下结果。为方便起见,我将跳过 ⱯA.
符号。
Nothing
<:Option[A]
, 所以Option[A] => string
<:Nothing => string
- 我想不出任何
Nothing => string
的实例不是Option[A] => string
的实例,所以Nothing => string
<:Option[A] => string
Nothing => string
(<: 和>:)Option[A] => string
,因此Nothing => string
在子类型 中实际上等于 Option[A] => string
<:Some[A] => string
, 所以Nothing => string
<:Some[A] => string
Some[A]
<:Nothing
Option[A] => string
由于我强烈怀疑结果是否正确,我认为中间出了问题。谁能解释一下这里发生了什么?
我会简单地拆开每一步。
Nothing
不接受任何类型参数。您可能是指None
,它属于None.type
类型,而后者又是Option[Nothing]
.- 为什么不呢?
-
def foo(n: None.type): String = "blah"
println(foo(None)) // ok
// println(foo(Some("string"))) // doesn't compile.
- 错误。
- 原则上传递性正确,但前一步错误
- 错误,因为之前的步骤错误。为什么这个推理应该普遍成立尚不完全清楚。
所以,没有。现在你可以想到一个接受 None
而不是一般 Option
.
注:None.type
是单例对象的类型None
。一般来说,单例对象的类型Obj
是Obj.type
.
我认为你混淆了一些东西。我认为A -> B
应该是A => B
,一个从A
到B
的函数。接下来, Nothing[A]
不存在,只有 Nothing
是 Scala 中的底层类型(sub-type 所有类型)。但你可能指的是对象 None
(类型为 None.type
),它是 Option
的 sub-type。
那么你的第一个假设是正确的:
implicitly[None.type <:< Option[_]] // ok
implicitly[(Option[_] => String) <:< (None.type => String)] // ok
我改写你的第二个假设:
I cannot think of any instance of
None.type => String
that is not an instance ofOption[A] => String
, so(None.type => String) <: (Option[A] => String)
这个假设是错误的:
implicitly[(None.type => String) <:< (Option[_] => String)]
error: Cannot prove that None.type => String <:< Option[_] => String. implicitly[(None.type => String) <:< (Option[_] => String)] ^
可能很难想象,因为None
不会添加任何不属于Option
接口的方法。但以一般动物(如Option
)和特殊动物(如None
)为例
trait Animal // aka Option
object Dog extends Animal { def bark() = "bark!" }
object Cat extends Animal { def purr() = "purr!" } // aka None
你的第二个假设意味着 (Cat => String) <: (Animal => String)
。如果为真,则可能出现以下情况:
val fun: Animal => String = { c: Cat.type => c.purr } // doesn't compile
让我们强制:
val fun: Animal => String = { c: Cat.type => c.purr } .asInstanceOf[Animal => String]
fun(Dog) // try run this
java.lang.ClassCastException: Dog$ cannot be cast to Cat$ ... 64 elided