【发布时间】:2017-09-04 04:08:07
【问题描述】:
我遇到了我无法理解的类型检查错误。两段代码相似,但只有一段可以编译。编译器给出完全无用的错误信息:
错误:类型参数 [I] 不符合类型 DY 的类型参数界限 [I <: sample.this.y>
有问题的代码:
trait Sample {
type X
type DX[I <: X] <: X
type Y = Aux[X]
type DY[I <: Y] <: Y
type Z = Bux[X]
type DZ[I <: Z] <: Z
type DW[I <: Z#C] <: Z#C
}
type Aux[I] = Sample { type X = I }
trait Dep {
type B
type C = Aux[B]
}
type Bux[A] = Dep { type B = A }
type UseX[I <: S#X, S <: Sample] = S#DX[I] // ok
type UseY[I <: S#Y, S <: Sample] = S#DY[I] // fails
type UseZ[I <: S#Z, S <: Sample] = S#DZ[I] // ok
type UseW[I <: S#Z#C, S <: Sample] = S#DW[I] // fails
为什么我不能引用类型本身?
更新
我和我写这个问题时一样困惑。但我仍然设法欺骗编译器完成他的工作。这只会加剧我的困惑。
问题是基于类型绑定接受或拒绝相同类型的参数。如果类型绑定与参数相同(因此引入递归),则它被拒绝。但是,如果我将递归包装在一个类型中,它通常会被接受。所以我只需要中继递归调用
trait Sample {
type X
type Y = Aux[X]
type Z = Bux[X]
type DY[I <: Y] <: Y
type DD[I <: Z] = DY[I#C]
}
type UseY[I <: S#Y, S <: Sample] = S#DY[I] // still fails
type UseD[I <: S#Z, S <: Sample] = S#DD[I] // miraculously works
但它需要将每个类型级别的调用包装在 Bux 包装器类型中。
【问题讨论】:
-
添加编译错误会有所帮助
-
我把错误放在代码前面。
-
它有一个循环,设计成这样?
-
是的。我在实现某种类型列表时遇到错误,该类型列表本质上是递归结构。之后,我将代码简化为最小的可重现示例。请注意,使用
Z仍然可以,即使它包含递归但没有显式调用它。 -
这个编译:
type UseY[I <: S#Y, S <: Aux[I]] = S#DY[I]type UseW[I <: S#Z#C, S <: Aux[I]] = S#DW[I]