I have this standard Shapeless
code:
case class KeyValue(key: String, value: Int)
val kv = KeyValue("key", 1)
def processCaseClass(p: KeyValue) = {
val gen = LabelledGeneric[KeyValue]
gen.to(p)
}
But instead of using the name of the case class, I'd like to use generics, however, rewriting it this way, does not work:
def processCaseClass[KV <: Product, L <: HList](p: KV) = {
val gen = LabelledGeneric.Aux[KV, L]
gen.to(p)
}
If I change gen
to an implicit parameter it works OK.
What is wrong with the above code?
Making a method generic in T
makes it clueless as to what T
is. If processCaseClass
doesn't know what KV
is, it stands no chance of analyzing its structure enough to make a LabelledGeneric[KV]
, producing an implicit resolution error. By making it an implicit parameter, you shift the responsibility of producing the LabelledGeneric
to the caller, where it actually stands a chance of being satisfied, because the caller will know what PK
is.
An odd thing that your first definition of processCaseClass
does is this, which should suffice to show that it cannot be correct:
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?