eddiemundorapundo
eddiemundorapundo

Reputation: 147

What is the reason this type parameter syntax doesn't compile?

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

Answers (2)

Malte Schwerhoff
Malte Schwerhoff

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

Petr
Petr

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

Related Questions