从泛型生成无形记录
Generate Shapeless Record from Generics
我有这个标准Shapeless
代码:
case class KeyValue(key: String, value: Int)
val kv = KeyValue("key", 1)
def processCaseClass(p: KeyValue) = {
val gen = LabelledGeneric[KeyValue]
gen.to(p)
}
但是我不想使用案例的名称 class,而是想使用泛型,但是,这样重写它是行不通的:
def processCaseClass[KV <: Product, L <: HList](p: KV) = {
val gen = LabelledGeneric.Aux[KV, L]
gen.to(p)
}
如果我将 gen
更改为隐式参数,它就可以正常工作。
上面的代码有什么问题?
在 T
中使一个方法泛化会使它对 T
是什么一无所知。如果 processCaseClass
不知道 KV
是什么 ,它就没有机会分析其结构足以生成 LabelledGeneric[KV]
,从而产生隐式解析错误。通过将其设为隐式参数,您将生成 LabelledGeneric
的责任转移给了调用者,它实际上有机会得到满足,因为调用者将知道 PK
是什么。
你对 processCaseClass
的第一个定义做的一件奇怪的事情是这样的,这应该足以表明它不可能是正确的:
def processCaseClass[KV <: Product, L <: HList](p: KV): Any // Signature of pCC
// Function body doesn't affect sig., aside from return type, so what you write is what you get
// A sig. is the only interface between a method and the world. This method doesn't
// say there's a relationship between KV and L in its signature, so there doesn't
// need to be one.
// Instantiate KV = (Int, Int), L = String :: String :: HNil, p = (5, 5)
val x = processCaseClass[(Int, Int), String :: String :: HNil]((5, 5))
// Perfectly valid to the compiler... but what is this supposed to do?
我有这个标准Shapeless
代码:
case class KeyValue(key: String, value: Int)
val kv = KeyValue("key", 1)
def processCaseClass(p: KeyValue) = {
val gen = LabelledGeneric[KeyValue]
gen.to(p)
}
但是我不想使用案例的名称 class,而是想使用泛型,但是,这样重写它是行不通的:
def processCaseClass[KV <: Product, L <: HList](p: KV) = {
val gen = LabelledGeneric.Aux[KV, L]
gen.to(p)
}
如果我将 gen
更改为隐式参数,它就可以正常工作。
上面的代码有什么问题?
在 T
中使一个方法泛化会使它对 T
是什么一无所知。如果 processCaseClass
不知道 KV
是什么 ,它就没有机会分析其结构足以生成 LabelledGeneric[KV]
,从而产生隐式解析错误。通过将其设为隐式参数,您将生成 LabelledGeneric
的责任转移给了调用者,它实际上有机会得到满足,因为调用者将知道 PK
是什么。
你对 processCaseClass
的第一个定义做的一件奇怪的事情是这样的,这应该足以表明它不可能是正确的:
def processCaseClass[KV <: Product, L <: HList](p: KV): Any // Signature of pCC
// Function body doesn't affect sig., aside from return type, so what you write is what you get
// A sig. is the only interface between a method and the world. This method doesn't
// say there's a relationship between KV and L in its signature, so there doesn't
// need to be one.
// Instantiate KV = (Int, Int), L = String :: String :: HNil, p = (5, 5)
val x = processCaseClass[(Int, Int), String :: String :: HNil]((5, 5))
// Perfectly valid to the compiler... but what is this supposed to do?