2017-09-15 3 views
1

Ich habe diesen Standard Shapeless Code:Shapeless Bilanz von Generics

case class KeyValue(key: String, value: Int) 
val kv = KeyValue("key", 1) 

def processCaseClass(p: KeyValue) = { 
    val gen = LabelledGeneric[KeyValue] 
    gen.to(p) 
} 

Aber statt die Namen der Fall-Klasse, würde Ich mag Generika verwenden, aber es so umschreiben, nicht Arbeit:

def processCaseClass[KV <: Product, L <: HList](p: KV) = { 
    val gen = LabelledGeneric.Aux[KV, L] 
    gen.to(p) 
} 

Wenn ich gen auf einen impliziten Parameter ändern funktioniert es OK.

Was ist mit dem obigen Code falsch?

Antwort

2

Eine generische Methode in T macht es ahnungslos was T ist. Wenn nicht weiß, was KV ist, hat es keine Chance, seine Struktur so zu analysieren, dass ein LabelledGeneric[KV] entsteht, was zu einem impliziten Auflösungsfehler führt. Indem Sie es zu einem impliziten Parameter machen, verlagern Sie die Verantwortung, LabelledGeneric an den Anrufer zu senden, wo es tatsächlich eine Chance hat, zufrieden zu sein, weil der Anrufer weiß, was PK ist.

Eine seltsame Sache, die Ihre erste Definition processCaseClass tut, ist dies, die zeigen, genügen zu müssen, dass es nicht richtig sein kann:

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? 
+0

Sie für die Erklärung danken. Jetzt macht es Sinn. – jamborta