无法证明“ a Tuple2” <:<(T,U)

时间:2019-06-27 18:50:48

标签: scala

我正在尝试从输入映射中构建映射,但是编译器无法证明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

1 个答案:

答案 0 :(得分:6)

当您使用存在性来做事时,Scala有时会在类型推断上变幻无常(这就是Element[_]的意思)。快速的显式类型签名将解决此问题。

val output = input.map(e => e._1 -> makeList(e._1)).toMap[Int, Element[_]]

您要做的就是告诉编译器您想要键和值的类型。无法推理的原因漫长而复杂,但是作为一般规则,一旦开始在类型中添加下划线,就会失去一些推理功能。