为什么 deriveHCons 的签名在 Symbol 是最终的 class 时声明 `HK <: Symbol`

Why does the signature of deriveHCons declare `HK <: Symbol` when Symbol is a final class

Shapeless 的 LabelledProductTypeClassCompanionderiveHCons 的签名如下:

implicit def deriveHCons[HK <: Symbol, HV, TKV <: HList]
    (implicit
      ch: Lazy[C[HV]],
      key: Witness.Aux[HK],
      ct: Lazy[Wrap[TKV] { type V <: HList }]
    ): Wrap.Aux[FieldType[HK, HV] :: TKV, HV :: ct.value.V] = ...

Symbol 是最终的 class 时,我们声明一个必须派生自 Symbol 的类型参数 HK 对我来说似乎很奇怪。除了 Symbol 之外,其他东西怎么能替代类型参数 HK?如果 HK 始终是 Symbol,如果去掉 HK 并直接在类型签名中替换 Symbol,这个签名会不会更强大?

我将解释为什么这适用于 Int,但它实际上适用于 Symbol

Int 是最终的吧?这是它的一个实例:

val n = 2

但我们实际上可以给 n 一个比这更精确的类型。如何?随着 literal singleton types:

val n: Witness.`2`.T = 2

现在 n 的类型为 Witness.`2`.T、a.k.a。 2.type,或者只是 type 22 是其中唯一的居民,例如3: Witness.`2`.T 不会编译。我们有 Witness.`2`.T <: Int

同样的事情也适用于符号:虽然 Symbol 是最终的,但它的值,特别是文字值,可以被赋予更精细的类型,这些值对应于这些值:

val s = Symbol("s")
val refined: Witness.`'s`.T = Symbol("s")