2016-05-19 13 views
2

Es tut mir leid für solche nicht beschreibenden Titel, aber ich weiß wirklich nicht, wie man das besser ausdrücken kann.Was ist daran falsch (Compilerfehler)?

class Foo[T] 
Seq(new Foo[String], new Foo[Int]).groupBy(_ => 1).map { case (k, Seq(v)) => k -> v }.toMap 
<console>:12: error: Cannot prove that (Int, Foo[_146]) forSome { type _146 >: Int with String } <:< (T, U). 

WTF? Wenn ich .mapValues anstelle von .map verwende, funktioniert es. Auch macht es Foo kovariant behebt es auch, aber in diesem Fall am Ende mit Map[Int,Foo[Any]] Was ist hier los? Irgendwelche Ideen?

+2

welchen Typ * Sie * mit am Ende? – Bergi

+0

'Map [Int, Foo [_]]' wäre gut – Dima

Antwort

4

Ohne Varianz Sie eine etwas „unsinnig“ -Sequenz erstellen:

class Foo[T] 
val in = Seq(new Foo[String], new Foo[Int]) // Seq[_ >: Int with String]] 

Es gibt einfach keine gemeinsame LUB zwischen Foo[String] und Foo[Int] ist. Sie können es eine existenzielle Art zuordnen:

val in = Seq[Foo[_]](new Foo[String], new Foo[Int]) 

Dann können wir weiterhin versuchen:

val in = Seq[Foo[_]](new Foo[String], new Foo[Int]) 
val g = in.groupBy(_ => 1) // Map[Int, Seq[Foo[_]]] 
// the next line would produce a match error, thus make it a `def` 
def m = g.map { case (k, Seq(v)) => k -> v } // Iterable[(Int, Foo[_])] 
def p = m.toMap // cannot prove that (Int, Foo[_]) <:< (T, U) 

Wieder ist die existenzielle Art beißt man hier in eine nützliche Folgerung für den Werttyp disallowing. Sie können es erneut erzwingen:

def p = m.toMap[Int, Foo[_]] // Map[Int,Foo[_]] 

AFAIK, Scalac wird keine existentiellen Typen für Sie ableiten.


Wenn Sie denken, Sie Foo[Any] hier haben, müssen Sie eine Varianz Anmerkung hinzuzufügen:

class Foo[+T] 
val in = Seq(new Foo[String], new Foo[Int]) // Seq[Foo[Any]] 
def m = in.groupBy(_=>1).map {case (k,Seq(v)) => k->v}.toMap // Map[Int,Foo[Any]] 
+0

Ich will nicht 'Foo [Any]', ich möchte einen existentiellen Typ. '.toMap [Int, Foo [_]]' funktioniert, danke ... das ist die einzige Option, die ich nicht ausprobiert habe :) Ich verstehe immer noch nicht, warum '.map' und' .mapValues' anders funktionieren (der Letzteres funktioniert, und ich brauche nicht einmal '.toMap'- was überflüssig ist, da das Ergebnis von' .map' und '.mapValues' bereits eine Map ist. Warum funktioniert '.grouBy' überhaupt? Wenn der Typ die Werte angibt, wenn er nach 'groupBy' bekannt ist, sollte das Mapping der Werte auf head von seq es nicht schlechter machen, oder? – Dima