I was doing some experiments with existential types. First I defined a small class hierarchy:
trait Fruit
case class Apple extends Fruit
case class Banana extends Fruit
Then I wanted a set to which I could add different types of Fruit:
val set1: Set[_ >: Fruit] = Set()
// Which is equivalent to:
val set2: Set[F] forSome { type F >: Fruit } = Set()
// This compiles
set1 += Apple()
set1 += Banana()
set2 += Apple()
set2 += Banana()
So far, so good. But now I want a set of functions from some Fruit to Unit:
// This still compiles
val set3: Set[(_ <: Fruit) => Unit] = Set()
// But this doesn't
val set4: Set[F => Unit] forSome { type F <: Fruit } = Set()
That last line gives me the following errors:
- no type parameters for method apply: (elems: A*)scala.collection.mutable.Set[A] in class GenericCompanion exist so that it can be applied to arguments () --- because --- undetermined type
- type mismatch; found : scala.collection.mutable.Set[A] required: scala.collection.mutable.Set[F => Unit] forSome { type F <: Fruit }
Why do I get those errors, when supposedly my set4 is equivalent to set3? Did I made a mistake somewhere?
If I say Set[(F forSome { F <: Fruit }) => Unit] then that lines compiles, but I can't add functions to that set:
- type mismatch; found : Apple => Unit required: F forSome { type F <: Fruit } => Unit
Where I can add the same function to set3 with no problem.
Another problem I had is that I can't put the existential types on the right side of the assignment:
// Does not compile, I get "unbound wildcard type"
val set1 = Set[_ >: Fruit]()
Why is that?