2016-05-19 9 views
2

私はそのような非記述的なタイトルのために申し訳ありませんが、私は本当にこれをより良く表現する方法を知らない。これには何が問題なのですか(コンパイラのバグ)?

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? .mapの代わりに.mapValuesを使用すると動作します。また、Foo共変もそれを修正しますが、その場合は結局Map[Int,Foo[Any]] ここでは何が起こっていますか?何か案は?

+2

を? – Bergi

+0

'Map [Int、Foo [_]]'は良いでしょう – Dima

答えて

4

分散することなく、あなたはやや「無意味な」配列を作成します。そこだけではありませんFoo[String]Foo[Int]間に共通LUB

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

。その後、我々は継続しようとすることができ

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

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) 

再び実存型が値型のための便利な推論を許可しないで、ここであなたを噛むあなたは実存タイプを割り当てることができます。あなたは再びそれを強制することができます。

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

私の知る限り、Scalacはあなたのための実存の種類を推測しません。


あなたがここにFoo[Any]を持って考えている場合は、分散注釈を追加する必要があります:あなたは* *は、で終わるしたくない何種類

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

私は 'Foo [Any]'を望んでいません。実在するタイプが欲しいです。 '.toMap [Int、Foo [_]]'は動作します、ありがとうございます...それは私が試していない唯一のオプションです:)私はまだ '.map'と' .mapValues'が別々に動作する理由を理解していません後者はうまくいきます。私は '.toMap'を必要としません。これは' .map'と '.mapValues'の結果がすでにマップであるため冗長です。 また、最初に '.grouBy'が動作するのはなぜですか? 'groupBy'の後に値が分かっていれば、値をseqの頭にマッピングしてもそれを悪くしてはいけませんか? – Dima

関連する問題