2015-11-12 11 views
5

Versuchen, einen Weg zu finden, einen Fallkonstruktor so umzuformen, dass er einige Standardwerte ausfüllt. Ist folgendes möglich?Einen Fallklassenkonstruktor umformen?

def reshape[T, R1 <: HList, R2 <: HList](h: R1): R2 => T = ??? 

//example 
case class MyClass(a: Double, b: String, c: Int) 

val newConstructor = reshape[MyClass]('b ->> "bValue" :: HNil) 

newConstructor('a ->> 3.1 :: 'c ->> 4 :: HNil) 
res1: MyClass = MyClass(3.1, "bValue", 4) 

Ist es möglich mit formlos oder müssen wir den Makro-Route gehen?

Antwort

7

Es ist möglich, einen solchen Umformer fast ohne Änderung in Ihrem Code oder in benutzerdefinierten Typklassen zu erstellen. Wir werden nur prepend Argumentlisten und dann align Ergebnis LabelledGeneric[MyClass]#Repr:

import shapeless._ 
import syntax.singleton._ 
import ops.hlist._ 

class PartialConstructor[C, Default <: HList, Repr <: HList] 
(default: Default) 
(implicit lgen: LabelledGeneric.Aux[C, Repr]) { 
    def apply[Args <: HList, Full <: HList] 
    (args: Args) 
    (implicit prepend: Prepend.Aux[Default, Args, Full], 
    align: Align[Full, Repr]): C = 
    lgen.from(align(default ++ args)) 
} 

class Reshaper[C]() { 
    def apply[Default <: HList, Repr <: HList] 
    (default: Default) 
    (implicit lgen: LabelledGeneric.Aux[C, Repr]) = 
    new PartialConstructor[C, Default, Repr](default) 
} 

def reshape[C] = new Reshaper[C] 
+0

Dank! das Vorbereiten und Ausrichten ist sicherlich was ich suche. – KailuoWang