Null 和 Null & T 类型之间有什么区别,其中 T <: AnyRef?

问题描述 投票:0回答:1

看下面的方法

def toOption[T <: AnyRef](value: T | Null): Option[T] = 
    value match {
        case null => None
        case content: T => Some(content)
    }

如果你检查

content
模式变量,类型是
T | T & Null
,我猜这是被检查者
value: T | Null
的类型和匹配模式
element: T
的类型交集的结果。 引起我注意的是
|
运算符的第二个操作数。当
T & Null
Null
保留为
T<:AnyRef
的类型时,编译器不应该将
T | Null
部分简化为
content
吗?
Null
T & Null
类型有什么区别?

如果交集

A & B
的定义是它表示同时属于
A
B
的成员的值,则:

  • 如果
    T
    表示的值包含
    null
    ,则同时属于
    T
    Null
    的值集将仅包含
    null
    值;
  • 如果
    T
    表示的值不包括
    null
    ,则同时属于
    T
    Null
    的值集将为空 (
    Nothing
    )。

因此,当

T & Null
时,
Null | Nothing
=
Null
=
T <: AnyRef

如果交集

A & B
的定义是一个值符合
A & B
意味着它同时符合
A
B
,那么:

  • 如果
    null
    符合
    T
    那么只有
    null
    才会同时符合
    T
    Null
  • 如果
    null
    不符合
    T
    ,则任何值都不会同时符合
    T
    Null

因此

T & Null
=
Null | Nothing
=
Null
T <: AnyRef
时。

我遗漏了什么或者编译器有错误吗?


编辑:我忘了提及我正在使用intelliJ进行检查。后来为了确认,我用宏根据编译器显示的是

content
的类型,结果是
T
。与 IntelliJ 检查显示的非常不同。 我将 IntelliJ 检查器的错误归咎于编译器。对不起。

这是宏:

inline def typeOf[A](a: A): String = ${typeOfMacro[A]('{a})}

def typeOfMacro[A : Type](a: Expr[A])(using q: Quotes): Expr[String] = 
    Expr(q.reflect.TypeRepr.of[A].show)

无论如何,当

A & Null
时,scala REPL 不会将
Null
简化为
A <: AnyRef

scala> val text: String & Null = null
val text: String & Null = null

所以这个问题仍然存在。

奇怪的是 REPL 也没有将

A & Nothing
简化为
Nothing


编辑2:根据类型理论,不存在类型

X
使得对于任何
A & X
X
A
相同。所以我期望的简化是不正确的。 REPL 给出了正确的类型。所以我的问题的答案是是的,我错过了一些东西

scala scala-3
1个回答
0
投票

问题有点多,我就从基础开始吧

Scala 基于 DOT 演算。在 Scala 中,每个类型

T
都是一个类型段
[LowerBound, UpperBound]

T <: AnyRef
并不意味着
T >: Null
,反之亦然。

T <: AnyRef
表示类型段
[Nothing, AnyRef]
T >: Null
表示
[Null, Any]

AnyRef
是所有引用类型的超类型。
Null
是所有引用类型的子类型。
Null
仅由
null
居住。

Nothing
是所有类型的子类型(包括
Null
Nothing <: Null
Nothing != Null
)。它没有(正常)值。但没有(正常)值并不意味着
Nothing
根本没有任何东西。有这种类型的术语:
t: Nothing
,有与此类型相交的抽象类型/类型参数:
T >: Nothing
(并且在类型级编程中,类型更重要,值,无论存在与否,都不那么重要) ,没有像

这样正常的值
@tailrec
def infiniteRecursion(): Nothing = infiniteRecursion()

def throwException(): Nothing = throw new RuntimeException("error")
def foo[T <: AnyRef](t: => T): Unit = ()

foo[Nothing](infiniteRecursion()) // compiles, runs, successfully finishes

foo[Nothing](throwException())  // compiles, runs, successfully finishes

如果

T <: AnyRef
隐含
T >: Null
,则
foo[Nothing](infiniteRecursion())
foo[Nothing](throwException())
将无法编译。

如果您想要同时使用

T <: AnyRef
T >: Null
,则只需指定两个类型边界即可:

def foo[T >: Null <: AnyRef] = ...

T & Null
时,编译器不应该将
Null
部分简化为
T <: AnyRef

吗?

不,不应该。应该是

T >: Null
(包括
T >: Null <: AnyRef
)。

Null
T & Null
类型有什么区别?

如果

T = Nothing
那么
T & Null = Nothing & Null = Nothing != Null
。如果
T >: Null
那么
T & Null = Null
。如果
T <: Null
(即
T
属于段
[Nothing, Null]
),则
T & Null = T
。如果
T
只是某种类型,那么
T & Null
只是某种类型
<: T
<: Null

如果交集的定义...

  • 如果值...
  • 如果值...

类型不是(值)集合。如果两种类型具有相同的这些类型的值集,则这并不意味着类型相等。

例如下面的类型

Nat
Succ[N]
_0
_1
_2
、... 是抽象的,没有值。但它们是完全不同的类型。如果类型是集合,那么所有类型都将是同一集合(即空集)。

type Nat
type _0 <: Nat
type Succ[N <: Nat] <: Nat

trait Add[N <: Nat, M <: Nat] {
  type Out <: Nat
}
object Add {
  type Aux[N <: Nat, M <: Nat, Out0 <: Nat] = Add[N, M] { type Out = Out0 }

  implicit def zeroAdd[M <: Nat]: Aux[_0, M, M] = null
  implicit def succAdd[N <: Nat, M <: Nat](implicit
    add: Add[N, M]
  ): Aux[Succ[N], M, Succ[add.Out]] = null
}

type _1 = Succ[_0]
type _2 = Succ[_1]
type _3 = Succ[_2]
type _4 = Succ[_3]
type _5 = Succ[_4]

implicitly[Add.Aux[_2, _3, _5]] // compiles

trait ToInt[N <: Nat] {
  def apply(): Int
}
object ToInt {
  implicit val zeroToInt: ToInt[_0] = () => 0
  implicit def succToInt[N <: Nat](implicit toInt: ToInt[N]): ToInt[Succ[N]] =
    () => toInt() + 1
}

trait AddToInt[N <: Nat, M <: Nat] {
  def apply(): Int
}
object AddToInt {
  implicit def mkAddToInt[N <: Nat, M <: Nat, Sum <: Nat](implicit
    add: Add.Aux[N, M, Sum],
    toInt: ToInt[Sum]
  ): AddToInt[N, M] = () => toInt()
}

def addToInt[N <: Nat, M <: Nat](implicit addToInt: AddToInt[N, M]): Int = addToInt()

addToInt[_2, _3] // 5

根据类型理论,对于任何

X
,不存在
A & X
X
相同的类型
A

其实

X
就是
Nothing

© www.soinside.com 2019 - 2024. All rights reserved.