If you want to do this without casting (even within get ), you will need to write a heterogeneous map. For reasons that should be obvious, this is complicated. :-) The simplest way would probably be to use an HList like structure and build the find function. However, this is not trivial, since you need to define some way of checking type equality for two arbitrary types.
I tried to get a little confused with tuples and existential types. However, Scala does not provide a join mechanism (pattern matching does not work). In addition, subtyping ties it all together in nodes and basically eliminates any security that it could provide:
val xs: List[(Class[A], A) forSome { type A }] = List( classOf[String] -> "foo", classOf[Int] -> 42) val search = classOf[String] val finalResult = xs collect { case (`search`, result) => result } headOption
In this example, finalResult will be of type Any . This is actually correct, since subtyping means that we know nothing about A This is not why the compiler chooses this type, but it is the right choice. Take for example:
val xs: List[(Class[A], A) forSome { type A }] = List(classOf[Boolean] -> 'bippy)
This is absolutely legal! Subtyping means that A in this case will be selected as Any . This is hardly what we want, but this is what you get. Thus, in order to express this restriction without tracking all types individually (using the HMap ), Scala would have to be able to express the restriction that the type is a specific type, and nothing more. Unfortunately, Scala does not have this ability, so we mainly focus on the general restriction.
Refresh Actually, this is not legal. Just tried it and the compiler kicked it out. I think that it worked only because Class is invariant in its type parameter. So, if Foo is a certain type that is invariant, you should be safe from this case. It still does not solve the problem of unification, but at least it sounds. Unfortunately, type constructors are supposed to be in a magical superposition between co-, contra- and invariance, so if this is really an arbitrary type Foo form * => * , then you are still immersed in an existential front.
In short: this should be possible, but only if you fully encode Instances as an HMap . Personally, I would just throw get inside. Much easier!