Search code examples
scalaclassinheritancetypesexistential-type

Scala Existential type weird behavior


I have the following in my REPL:

scala> trait T[A]
defined trait T

scala> :kind T[A] forSome {type A}
T[_]'s kind is A

scala> :kind T[_]
T[_]'s kind is A

Now when i do:

trait e[_] extends T[_]

I get

error: class type required but T[_] found

However the following works:

scala> trait e[_] extends T[Int]
defined trait e

With

scala> :kind T[Int]
T[Int]'s kind is A

Why is T[Int] treated differently from T[_], while they are of the same Kind ?


Solution

  • It's not about kind, it's about whether a type is a class type (including traits) or not.

    You can write

    type T <: U
    

    for every type U but

    trait T extends U
    

    only for a class type U.

    Subtyping and inheritance/subclassing are different.

    The type corresponding to a trait T[A] is a class type for every type A. So T[Int] is a class type. (When you write extends A[B] it's important that A is a class type, B can be arbitrary type.)

    Existential type (like T[_] aka T[A] forSome {type A}) is not a class type. (You can also think of T[_] as a supertype of all T[A]. Actually, T[_] is the least upper bound of all T[A]).