为什么某些递归类型无法编译

时间:2017-08-17 07:45:44

标签: scala types

我遇到了我无法理解的类型检查错误。两段代码是相似的,但只有一段编译。编译器提供完全无用的错误消息:

  

错误:类型参数[I]不符合类型DY的类型参数边界[I&lt ;: 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包装器类型中包装每个类型级别的调用。

1 个答案:

答案 0 :(得分:1)

因此,S#Y表示“某些类型Y,在 S的任何实例中定义。 另一方面,type DY[I <: Y]表示“I必须是实例中声明的Y的子类”。

因此,当您说type UseY[I <: S#Y, S <: Sample] = S#DY[I]时,它会失败,因为I被限制为来自某些 Y的{​​{1}}的子类,但是S希望它是的子类 DY,其中声明了S