2016-07-29 8 views
1

ich den folgenden Code haben, im Grunde durch die Felder eines case class iterieren und sie ordnen ein Poly auf die gleiche Art und verwenden ToList[HL, Out]Shapeless: Wie auszudrücken <: Fall-Klasse Typ param für Generix.Aux

der Einfachheit halber können wir die Poly annehmen tut dies:

object Schema extends Poly1 { 
    implicit def caseInt = at[Int](_ => "I'm an int") 
    implicit def caseString = at[String](_ => "Oh boy a string") 
} 

def infer[V1 <: Product, Out <: HList, MapperOut <: HList](v1: V1)(
    implicit gen: Generic.Aux[V1, Out], 
    map: Mapper.Aux[Schema.type, Out, MapperOut], 
    to: ToList[MapperOut, String] 
): List[String] = to (gen to v1 map Schema) 

das alles ist sehr einfach und funktioniert sehr gut für einfache Szenarien:

case class Test(id: Int, text: String) 
val list = infer(Test(2, "text")) 
// List("I'm an int", "Oh boy a string") 

gehen nun heraus, wo die Busse fahren nicht:

class Automagical[T <: Product with Serializable : TypeTag] { 
    def instance: T 
    // The typetag bit is needed for something else 
    def convert: List[String] = infer(instance) 
} 

Leider jeder Anruf oben nicht mit:

could not find implicit value for parameter gen: shapeless.Generic.Aux[T,Out] 

Bonus

Wie kann ich die infer Methode verbessern indem man überhaupt keine Instanz T benötigt? Typ Offensichtlich Folgerung ist in Ordnung, aber ich muss irgendwie ein List[String] von einem HList[Lub] materialisieren und Karte über etwas.

Da ich nur Pflege jemals über die Art ist es möglich, eine konkrete Instanz List[String], indem nur die Typen wissen abzuleiten Poly gemappt werden codiert als ein HList?

Etwas wie:

def infer[V1 <: Product, Out <: HList, MapperOut <: HList]()(
    implicit gen: Generic.Aux[V1, Out], 
    map: Mapper.Aux[Schema.type, Out, MapperOut], 
    to: ToList[MapperOut, String] 
): List[String] = { 
    // Magically build an HList with samples from its types. 
    // Or an alternative approach that gives the same outcome 
    val reifiedInstance = reify[Out] 
    to (reifiedInstance map Schema) 
} 
+0

'Automagical' Eigenschaft lässt sich nicht kompilieren für mich:„Traits nicht Typparameter mit Kontext Grenzen haben“, aber natürlich der Fehler Sie tritt auch mit einer abstrakten Klasse erwähnt. – devkat

+0

@devkat Mein Fehler, das war eine Klasse in der ursprünglichen Implementierung. – flavian

Antwort

1

Um sicherzustellen, dass convert Zugriff auf die impliziten Parameter für infer hat, müssen diese vorhanden sein, wenn die Automagical Instanz erstellt wird:

Der
+0

Das würde es in meinem Fall zu einem Nein machen, da ich 'Automagical' brauche, um eine Typklasse zu sein. – flavian

+0

Ich akzeptierte die Antwort, da sie dieses spezielle Problem löst. Gibt es eine Möglichkeit, mit der Sache umzugehen, die du nicht kennst? – flavian

+0

Scalacheck-formlos (https://github.com/alexarchambault/scalacheck-shapeless) können Beispielinstanzen für Fallklassen, wahrscheinlich über 'HLists' erstellen. Vielleicht lohnt es sich herauszufinden, wie es dort gemacht wird. – devkat