为什么java.lang.Integer和java.lang.Double的最小上限被推断为非循环类型?

soc*_*soc 16 generics types scala type-inference

考虑以下代码:

val foo = if(true) 
            new java.lang.Double(4) 
          else
            new java.lang.Integer(4)
Run Code Online (Sandbox Code Playgroud)

推断类型foo是:

Number with Comparable[_ >: Double with Integer <: Number with 
  Comparable[_ >: Double with Integer <: Number]]
Run Code Online (Sandbox Code Playgroud)

所以基本上编译器在第三次递归后在边界和中止上循环.

以下为什么不够?

Number with Comparable[_ >: Double with Integer <: Number]
Run Code Online (Sandbox Code Playgroud)

huy*_*hjl 8

不是答案,而是在REPL中隐含使用的一些线索.编译器认为类型不相同.推断类型更具体:

// some type aliases to make reading easier
type Dx = java.lang.Double
type Ix = java.lang.Integer

// the type the compiler came up with:
type Inferred = Number with Comparable[
  _ >: Dx with Ix <: Number with Comparable[_ >: Dx with Ix <: Number]]

// your type:
type Soc = Number with Comparable[_ >: Dx with Ix <: Number]
Run Code Online (Sandbox Code Playgroud)

检查我做了右边的类型别名:

val d = new java.lang.Double(4)
val i = new java.lang.Integer(4)
val foo: Soc = if (true) d else i
// foo: Soc = 4.0
val foo: Inferred = if (true) d else i
// foo: Inferred = 4.0
Run Code Online (Sandbox Code Playgroud)

类型不一样:

implicitly[Soc =:= Inferred] // error
Run Code Online (Sandbox Code Playgroud)

您的类型是推断类型的超类型:

implicitly[Inferred <:< Soc] // ok
implicitly[Soc <:< Inferred] // error
Run Code Online (Sandbox Code Playgroud)

所以根据编译器,它提出了一个更具体的类型 - 这是正确的做法.请注意,可以像这样重新创建用例:

class N                     // like java.lang.Number

trait C[T]                  // like Comparable

class I extends N with C[I] // like java.lang.Integer
class D extends N with C[D] // like java.lang.Double

type DI = N with C[_ >: D with I <: N with C[_ >: D with I <: N]]
// DI is like the type inferred

type DI_SOC = N with C[_ >: D with I <: N] // your type

val foo: DI = if (true) new D else new I     // ok
val foo: DI_SOC = if (true) new D else new I // ok

implicitly[DI =:= DI_SOC] // error
implicitly[DI <:< DI_SOC] // DI_SOC super type of DI
implicitly[DI_SOC <:< DI] // error
Run Code Online (Sandbox Code Playgroud)

所以我想知道我们是否可以创建一个类DI_SOC但不是a 的类,DI它将说明DI并且DI_SOC不是相同的类型,并且您的类型不是最小的上限.

好吧,在踩了一下电脑然后再试一次.这是一个类,DI_SOC但不是DI:

class A extends N with C[N]
implicitly[A <:< DI_SOC] // ok
implicitly[A <:< DI]     // error
Run Code Online (Sandbox Code Playgroud)

适用于原始用例:

class Ax extends Number with Comparable[Number] {
  def doubleValue() = 0d
  def floatValue() = 0f
  def intValue() = 0
  def longValue() = 0L
  def compareTo(n: Number) = 0
}

implicitly[Ax <:< Soc]      // ok
implicitly[Ax <:< Inferred] // error
Run Code Online (Sandbox Code Playgroud)

因此,类型SocInferred相同的,Ax证明Number with Comparable[_ >: Double with Integer <: Number]不是最少的上限...

换句话说,两者之间有一些空间,Double with Integer <: ? <: Number但两者之间并不多Double with Integer <: ? <: Number with Comparable[_ >: Double with Integer <: Number]