这有什么问题(编译器错误)?

时间:2016-05-19 21:59:08

标签: scala type-inference existential-type

我很抱歉这样的非描述性标题,但我真的不知道如何更好地表达这一点。

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? 如果我使用.mapValues代替.map,则可行。此外,制作Foo协变也会修复它,但在这种情况下,我最终会使用Map[Int,Foo[Any]] 这里发生了什么?有什么想法吗?

1 个答案:

答案 0 :(得分:4)

如果没有差异,你会创建一个有点无意义的&#34;序列:

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

Foo[String]Foo[Int]之间根本没有共同的LUB。您可以为其指定一个存在类型:

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[_]]

AFAIK,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]]