I want to use a map of varying types on an unknown A:
val map: Map[Foo[A], Bar[A]] = ...
...
val foo = new Foo[Qux]
val bar: Bar[Qux] = map(foo)
This doesn't work, because A is an unknown. I have to define it instead as:
val map: Map[Foo[_], Bar[_]] = ...
...
val foo = new Foo[Qux]
val bar: Bar[Qux] = map(foo).asInstanceOf[Bar[Qux]]
This works, but the cast is ugly. I'd rather find a better way. I gather the answer is to use existential types with the forSome
keyword, but I'm confused as to how that works. Should it be:
Map[Foo[A], Bar[A]] forSome { type A }
or:
Map[Foo[A] forSome { type A }, Bar[A]]
or:
Map[Foo[A forSome { type A }], Bar[A]]
Actually, none of these work.
Map[Foo[A], Bar[A]] forSome { type A }
is a Map
where all keys are of the same type Foo[A]
and values of type Bar[A]
(but the type A
may be different for different maps of this type); in second and third examples, A
in Bar[A]
is completely different from A
under forSome
.
This ugly workaround should work:
// need type members, so can't use tuples
case class Pair[A, B](a: A, b: B) {
type T1 = A
type T2 = B
}
type PairedMap[P <: Pair[_, _]] = Map[P#T1, P#T2]
type FooBarPair[A] = Pair[Foo[A], Bar[A]]
val map: PairedMap[FooBarPair[_]] = ...