为什么 deriveHCons 的签名在 Symbol 是最终的 class 时声明 `HK <: Symbol`
Why does the signature of deriveHCons declare `HK <: Symbol` when Symbol is a final class
Shapeless 的 LabelledProductTypeClassCompanion
中 deriveHCons
的签名如下:
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 2
。 2
是其中唯一的居民,例如3: Witness.`2`.T
不会编译。我们有 Witness.`2`.T <: Int
同样的事情也适用于符号:虽然 Symbol
是最终的,但它的值,特别是文字值,可以被赋予更精细的类型,这些值对应于这些值:
val s = Symbol("s")
val refined: Witness.`'s`.T = Symbol("s")
Shapeless 的 LabelledProductTypeClassCompanion
中 deriveHCons
的签名如下:
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 2
。 2
是其中唯一的居民,例如3: Witness.`2`.T
不会编译。我们有 Witness.`2`.T <: Int
同样的事情也适用于符号:虽然 Symbol
是最终的,但它的值,特别是文字值,可以被赋予更精细的类型,这些值对应于这些值:
val s = Symbol("s")
val refined: Witness.`'s`.T = Symbol("s")