2015-09-08 10 views
5

Der folgende Code scheint offensichtlich genug zu kompilieren undMapping über hList innerhalb einer Funktion

case class Pair(a: String, b: Int) 

val pairGen = Generic[Pair] 

object size extends Poly1 { 
    implicit def caseInt = at[Int](x => 1) 
    implicit def caseString = at[String](_.length) 
} 

def funrun(p: Pair) = { 
    val hp: HList = pairGen.to(p) 
    hp.map(size) 
} 

laufen, aber der Compiler sagt „nicht implizite Wert für den Parameter Mapper finden konnte“. In meinem Anwendungsfall möchte ich über einen HList abbilden, um und HList von String (s) zu erhalten und dann den HList von String (s) in Scala List [String] umwandeln. Irgendwelche Ideen?

Antwort

8

Zuerst können wir eine Poly1 ähnlich wie size schaffen, die wir eine HList zur Karte zu einem HList von Strings verwenden können.

object strings extends Poly1 { 
    implicit def caseInt = at[Int](_.toString) 
    implicit def caseString = at[String](identity) 
} 

wurden Sie bereits mit Generic[Pair] ein Pair in eine HList zu drehen, aber man konnte über Ihre hp nicht zuordnen, weil es keine Beweise in Ihrem funrun ist, dass Sie über sie abbilden. Wir können dies mithilfe impliziter Parameter lösen.

def funRun[L <: HList, M <: HList](
    p: Pair 
)(implicit 
    gen: Generic.Aux[Pair, L], 
    mapper: Mapper.Aux[strings.type, L, M] 
) = gen.to(p).map(strings) 
  • Unsere erste impliziten Parameter gen können eine Pair in ein HList des Typs drehen L.
  • Unser zweiter impliziten Parameter mapper können unsere strings polymorphe Funktion M eine HList vom Typ L zu einem HList des Typs abzubilden.

Wir können jetzt funRun verwenden, um einen Pair in eine HList von Strings zu drehen:

scala> funRun(Pair("abc", 12)) 
res1: shapeless.::[String,shapeless.::[String,shapeless.HNil]] = abc :: 12 :: HNil 

Aber Sie List[String] zurückkehren wollte. So schalten Sie unsere HListM (das Ergebnis der Zuordnung zu String) zu einem List[String] brauchen wir ein ToTraversable, also fügen wir eine dritte impliziten Parameter:

import shapeless._, ops.hlist._ 

def pairToStrings[L <: HList, M <: HList](
    p: Pair 
)(implicit 
    gen: Generic.Aux[Pair, L], 
    mapper: Mapper.Aux[strings.type, L, M], 
    trav: ToTraversable.Aux[M,List,String] 
): List[String] = gen.to(p).map(strings).toList 

Was können wir als verwenden:

scala> pairToStrings(Pair("abc", 12)) 
res2: List[String] = List(abc, 12) 
+0

Danke @Peter! Genau das habe ich gesucht! – arapmv

+0

Nachdem ich diesen Thread geschlossen habe, bin ich in Kreisen gegangen und habe versucht zu verstehen, warum die folgende Grundverbesserung zum zusammengesetzten Typ nicht funktioniert: 'Klasse A [T] (val x: T); Objekt g erweitert Poly1 { implizite def caseString = bei [String] {Identität} }; def toStr [L <: hList] ( a: A [String] ) (implizit Gene: Generic.Aux [A [String], L], Mapper: Mapper [g.type, L] ) = gen.to (a) .map (g) ' – arapmv

+0

Welchen Fehler bekommen Sie? –