Consider this code:
val foo = if(true)
new java.lang.Double(4)
else
new java.lang.Integer(4)
The inferred type for foo
is:
Number with Comparable[_ >: Double with Integer <: Number with
Comparable[_ >: Double with Integer <: Number]]
So basically the compiler loops on the bounds and aborts after the third recursion.
Why isn't the following enough?
Number with Comparable[_ >: Double with Integer <: Number]
Not an answer but some clues using implicitly in the REPL. The compiler doesn't think the types are the same. The inferred type is more specific:
// 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]
Checking I did the type aliases right:
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
Types are not the same:
implicitly[Soc =:= Inferred] // error
Your type is a super type of the inferred type:
implicitly[Inferred <:< Soc] // ok
implicitly[Soc <:< Inferred] // error
So according to the compiler, it came up with a more specific type - which would be the right thing to do. Note that the use case can be re-created like this:
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
So I wonder if we can craft a class that is a DI_SOC
but not a DI
, which would illustrate DI
and DI_SOC
are not the same types and your type is not the least upper bound.
Ok, after stepping out for the computer for a bit and then trying again. Here is a class that is a DI_SOC
but not a DI
:
class A extends N with C[N]
implicitly[A <:< DI_SOC] // ok
implicitly[A <:< DI] // error
Applied to the original use case:
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
Therefore, the types Soc
and Inferred
are not the same and Ax
proves that Number with Comparable[_ >: Double with Integer <: Number]
is not the least upper bound...
In other words, there is some room between Double with Integer <: ? <: Number
but not much between Double with Integer <: ? <: Number with Comparable[_ >: Double with Integer <: Number]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With