Reputation: 147
Say I have:
class Class[CC[A, B]]
class Thing[A, B <: Int]
class Test extends Class[Thing] // compile error here
I get the compiler error:
kinds of the type arguments (cspsolver.Thing) do not conform to the expected kinds of the type parameters (type CC) in class Class. cspsolver.
Thing's type parameters do not match type CC's expected parameters: type C's bounds <: Int are stricter than type B's declared bounds >: Nothing <: Any
However when I modify the code such that it looks like this:
class Class[CC[A, B]]
class Thing[A, B] {
type B <: Int
}
class Test extends Class[Thing]
it compiles fine. Aren't they both functionally equivalent?
Upvotes: 6
Views: 177
Reputation: 12852
Elaborating on Petr Pudlák's explanation, here is what I assume happens: The compiler tries to unify CC[A, B]
with Thing[A, B <: Int]
. According to the declaration of B
in CC
, B
's upper type-bound is Any
, which is picked to instantiate B
. The B
in Thing
, however, is expected to have Int
a its upper type-bound, and the compiler thus fails with the error message you got.
This is necessary in order to preserve soundness of the type system, as illustrated in the following sketch. Assume that Thing
defines an operation that relies on the fact that its B <: Int
, e.g.,
class Thing[A, B <: Int] {
def f(b: B) = 2 * b
}
If you declared Class
as
class Class[CC[A,B]] {
val c: CC
}
and Test
as
class Test extends Class[Thing] {
val t: Thing
}
without the compiler complaining, then you could make the following call
new Test().t.f(true)
which is obviously not safe.
Upvotes: 0
Reputation: 63379
The reason is given in the compiler message. In Class
you expect an unrestricted CC
, while Thing
has the restriction that the second type argument must be <: Int
. One possibility is to add the same constraint to Class
as in
class Class[CC[A,B <: Int]]
class Thing[A, B <: Int]
class Test extends Class[Thing]
Upvotes: 1