2017-02-23 3 views
2

Ich versuche, den folgend in scala zu erreichen, und dies scheint über meine „generischen“ Fähigkeiten zu sein:Scala Karte mit generischen Klassen als Schlüssel/Wert-Typ

Ich habe 2 generische Klassen:

class A[T] 
class B[T] 

und ich möchte einige kartieren zu einem gewissen Bs:

val m = Map[A, B] 

Nun, da nicht kompilieren, weil A und B generisch sind, so

val m = Map[A[_], B[_]] 

Ich möchte A/B-Paare für beliebige Typen T speichern. Ich möchte jedoch nur Paare hinzufügen, für die der generische Typ für den Schlüssel und den Wert identisch ist. So kann ich

m updated(new A[String], new B[String]) 

aber nicht

m updated(new A[String], new B[Int]) 

Und ich der Compiler sich dessen bewusst sein wollen, so kann ich

val a = new A[String] 
val b = new A[String] 
val m = Map(a -> b) 
val b: B[String] = m(a) // 

tun ich eine Bibliothek wie formlos denken konnte Hilfe ?

Antwort

3

Ich glaube, das erzwingt die Einschränkungen, nach denen Sie suchen.

class A[T] 
class B[T] 
val as = new A[String] 
val bs = new B[String] 
val ai = new A[Int] 
val bi = new B[Int] 
val ms: Map[A[X], B[X]] forSome {type X}= Map(as -> bs) // OK 
val mi: Map[A[X], B[X]] forSome {type X}= Map(ai -> bi) // OK 

Keine andere Kombinationen von as, bs, ai und bi kompiliert.

0

Ich denke, Ihre beste Wette ist, einen Wrapper um Scalas Map zu schreiben.

Meine sehr minimale Implementierung:

class MyMap[K[_],+V[_]] private(map: Map[Any,Any]) { 
    def apply[T](key: K[T]): V[T] = map(key).asInstanceOf[V[T]] 
    def updated[T1,T2,V1[X] >: V[X]](key: K[T1], value: V1[T2])(implicit ev: T1 =:= T2) = new MyMap[K,V1](map.updated(key,value)) 
} 

object MyMap { 
    def apply[K[_],V[_]] = new MyMap[K,V](Map.empty) 
} 

ich ein gegossenes intern verwenden, aber das sollte ziemlich sicher sein, da Ihnen sicher, dass die Schlüssel-Wert-Paare, die gehen in MyMap die gleichen Typargumente immer haben.

scala> val (ai,as,bi,bs) = (new A[Int], new A[String], new B[Int], new B[String]) 
ai: A[Int] = [email protected] 
as: A[String] = [email protected] 
bi: B[Int] = [email protected] 
bs: B[String] = [email protected] 

scala> var m = MyMap[A,B] 
m: MyMap[A,B] = [email protected] 

scala> m = m.updated(as,bs) 
m: MyMap[A,B] = [email protected] 

scala> m = m.updated(ai,bi) 
m: MyMap[A,B] = [email protected] 

scala> m(as) 
res0: B[String] = [email protected] 

scala> m(ai) 
res1: B[Int] = [email protected] 

Keine Vermischung:

scala> m = m.updated(ai,bs) 
<console>:23: error: Cannot prove that Int =:= String. 
     m = m.updated(ai,bs) 
        ^