Consider the following Scala code:
abstract class A
abstract class B[T <: A]
class ConcreteA extends A
class ConcreteB extends B[ConcreteA]
class Example
(See also two related questions: Scala fails to infer the right type arguments and Type infered to Nothing in Scala)
It looks like a limitation of Scala's type inference, which is intentionally not spec'ed. As work-around, you can get inference by making T
a type member of B
rather than parameter,
abstract class A
abstract class B { type T <: A }
class ConcreteA extends A
class ConcreteB extends B { type T = ConcreteA }
class Example[U <: B]( resolver: U )
object Test {
new Example( new ConcreteB )
}
When using type members, it's useful to know that they can be surfaced as type parameters using refinement, as in Miles Sabin's answer to: Why is this cyclic reference with a type projection illegal?
In Jean-Philippe Pellet's answer to a related question, type inference was aided by making the type parameter higher kinded. If you introduce an extra type parameter in ConcreteB
, then type inference can work,
abstract class A
abstract class B[T <: A]
class ConcreteA extends A
class ConcreteB[T <: A] extends B[T]
class Example[T <: A, U[T0 <: A] <: B[T0]]( resolver: U[T] )
object Test {
new Example( new ConcreteB[ConcreteA] )
}
Scala 2.9 gives the mysterious error message below, but Miles Sabin points out it is a bug that will be fixed for 2.9.1
:15: error: kinds of the type arguments (ConcreteA,ConcreteB[T0]) do not conform to the expected kinds of the type parameters (type T,type U) in class Example.
ConcreteB[T0]'s type parameters do not match type U's expected parameters: class ConcreteB has one type parameter, but type U has one
new Example( new ConcreteB[ConcreteA] )
^