Your ad is already working as intended, i.e. you restrict type T , as well as Key and Value . However, as you wrote it, scala will complain if you produce something like
scala> class Foo[T <: OtherT, Key[T], Value[T]] defined class Foo scala> new Foo[SpecialOtherT, Key[SpecialOtherT], Value[SpecialOtherT]] <console>:13: error: Key[SpecialOtherT] takes no type parameters, expected: one new Foo[SpecialOtherT, Key[SpecialOtherT], Value[SpecialOtherT]]
because the types of both Key and Value already set by your previous declaration. Therefore, it will work
scala> new Foo[SpecialOtherT, Key, Value] res20: Foo[SpecialOtherT,Key,Value] = Foo@3dc6a6fd
which you probably don't need. You could do it like this:
scala> class Foo[T <: OtherT, K <: Key[T], V <: Value[T]] defined class Foo scala> new Foo[SpecialOtherT, Key[SpecialOtherT], Value[SpecialOtherT]] res21: Foo[SpecialOtherT,Key[SpecialOtherT],Value[SpecialOtherT]] = Foo@7110506e
On the bottom line, since the types Key and Value depend exclusively on T , it is somewhat redundant to have all the redundant information when working with Foo . So, why not use an internal type declaration, for example:
class Foo[T <: OtherT] { type K = Key[T] type V = Value[T] }
Then you will have access to types K and V from the class, but you will not need to enter it every time you create a new answer:
scala> new Foo[SpecialOtherT] res23: Foo[SpecialOtherT] = Foo@17055e90 scala> new Foo[Int] <console>:11: error: ...