Scala 11.2给了我这个错误:
error: type mismatch;
found : Seq[Some[V]]
required: Seq[Option[?V8]] where type ?V8 <: V (this is a GADT skolem)
val output = f(ivs.map(iv => Some(iv.get._1)))
^
首先,这似乎是一个奇怪的错误信息:Seq [Some [V]]是否符合Seq [Option [V]]?
以下是周围代码的相似部分:
def evalDependencyTree[V]
(linkRelevance: LinkInfo => Option[LinkStrength])
(dtree: DependencyTree[V, LinkInfo], strengthSoFar: LinkStrength = 1.0)
: Option[(V, LinkStrength)] = dtree match {
. . .
case DFunction(f, inputs) => {
val ivs = inputs.map { input =>
evalDependencyTree(linkRelevance)(input, strengthSoFar) // <-- Recursive call
}
val output = f(ivs.map(iv => Some(iv.get._1))) // <-- The line with the error
. . .
}
}
trait DependencyTree[+V, +L]
case class DFunction[V, L](
f: Seq[Option[V]] => Option[V], inputs: Seq[DependencyTree[V, L]])
extends DependencyTree[V, L]
我(非常有限)对GADT skolems的理解是它们是类型推断期间编译器定义的类型,它复制现有的类型参数以防止该类型“转义”其作用域,如在递归调用中 - 也就是说,防止从无法访问该类型的更广泛的范围引用它。
我不知道V
如何在不同范围内引用不同类型。对evalDependencyTree
的递归调用与V
的当前调用具有相同的类型参数evalDependencyTree
。我尝试为递归调用显式编写evalDependencyTree[V]
,但编译器返回了相同的错误消息。当evalDependencyTree
没有类型参数时,此代码确实有效;在该版本中,dtree
被硬编码为DependencyTree[Int, LinkInfo]
。
什么类型试图逃脱?或者说,我做错了什么?
答案 0 :(得分:1)
我自己找到了一个解决方法:明确地在模式匹配中拼出完整类型的f
,如下所示:
case DFunction(f: Seq[Option[V]] => Option[V], inputs) => . . .
这有效,但我不接受它作为答案,因为我没有解释为什么它是必要的。我仍然不知道何时会发生这种错误或导致错误的原因。如果你知道,请发一个答案!
另外,我原本认为明确为f
提供的大部分类型都会因类型擦除而丢失。因此,我有两件重要的事情可以解释这个变通方法。