Higher type restriction in Scala

Say I have a higher type

SuperMap[Key[_],Value[_]]`. 

Suppose now that I had something even more specific that it was required that the type parameter for Key must match the type parameter for Value ; i.e. something like:

 SuperDuperMap[T, Key[T], Value[T]] 

Further suppose that I do not need only any T , but very specific, where T <: OtherT

 SuperDuperPooperMap[T <: OtherT, Key[T], Value[T]] 

Can this be done in Scala? Is this a bad idea? Is there an equivalent way to do this that is easier to read / write / use?

+7
source share
3 answers

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: ... 
+11
source

Can this be done in Scala?

What do you mean? You just did!

Is this a bad idea?

Why? This is actually a great idea! For this, types of a higher class are used.

Is there an equivalent way to do this that is easier to read / write / use?

Reading - it reads well for me.

Writing - write / test / compile once, use everywhere.

Usage - the compiler will reconstruct (derive) types everywhere.

+3
source

You probably don't need anything more complicated than a few type aliases,

 type SuperDuperMap[T, Key[_], Value[_]] = SuperMap[Key, Value] type SuperDuperPooperMap[T <: OtherT, Key[_], Value[_]] = SuperMap[Key, Value] 

Sample REPL Session,

 scala> new SuperDuperMap[Int, Option, List] {} res0: java.lang.Object with SuperDuperMap[Int,Option,List] = ... scala> new SuperDuperPooperMap[OtherT, Option, List] {} res1: java.lang.Object with SuperDuperPooperMap[OtherT,Option,List] = ... 
+2
source

All Articles