我正在尝试从输入映射中构建映射,但是编译器无法证明2元素元组是2元素元组。
代码
class Element[T] extends AnyRef { }
class Sample
{
def makeList(x:Int): Element[_] = {
x match {
case 1 => new Element[Boolean]
case 2 => new Element[(Boolean, Boolean)]
}
}
val input = Map(1 -> "one",2 -> "two")
val output = input.map(e => e._1 -> makeList(e._1)).toMap
}
sbt编译
sbt:root> ~compile
[info] Compiling 1 Scala source to /Users/tda0106/test/scala/target/scala-2.12/classes ...
[error] /Users/tda0106/test/scala/src/main/scala/Test.scala:14:57: Cannot prove that (Int, Element[_$1]) forSome { type _$1 } <:< (T, U).
[error] val output = input.map(e => e._1 -> makeList(e._1)).toMap
[error] ^
[error] one error found
[error] (Compile / compileIncremental) Compilation failed
[error] Total time: 1 s, completed Jun 27, 2019, 2:38:14 PM
问题似乎与forSome { type _$1 }
有关,否则应该匹配。当我第一次尝试重现它时,我使用List
而不是Element
进行编译。看来不同之处在于List
被声明为List[+T]
,而+
在这里很重要。
Element
来自第三方库,因此很难进行更改。
我在这里遇到什么问题,有没有简单的方法可以解决?
Scala版本:2.12.8
答案 0 :(得分:6)
当您使用存在性来做事时,Scala有时会在类型推断上变幻无常(这就是Element[_]
的意思)。快速的显式类型签名将解决此问题。
val output = input.map(e => e._1 -> makeList(e._1)).toMap[Int, Element[_]]
您要做的就是告诉编译器您想要键和值的类型。无法推理的原因漫长而复杂,但是作为一般规则,一旦开始在类型中添加下划线,就会失去一些推理功能。