Consider the following class definitions:
class Person[+T <: Person[T]]
class Student() extends Person[Student]
class Professor() extends Person[Professor]
I would like a list with a student and a professor:
val persons = List(new Student(), new Professor())
But this fails to compile with the following error:
type arguments [Person[Person[Any]]] do not conform to class Person's type parameter bounds [+T <: Person[T]]
Thanks to Daniel C. Sobral's answer to my related previous question How to define case classes with members with unbound type parameters? I know an existential type would do the trick here. This compiles:
val persons = List[Person[T] forSome {type T <: Person[T]}](new Student(), new Professor())
The problem is caused by the upper-bound <: Person[T]
in the type parameter of the class Person's declaration. Removing the upper-bound lets the compiler infer a type parameter for the list which makes it compile: List[Person[Person[Person[Any]]]]
as far as I can see.
Questions
- Why can't the compiler infer any type for the list which would make it compile?
- Existential types are to the least verbose and might furthermore be tricky (see Daniel's answer to my previous question linked above): Is there an alternative to explicit existential types for creating a list of students and professors?