2015-11-12 4 views
5

Пытается найти способ «переформатировать» конструктор case для заполнения некоторого значения по умолчанию. Возможно ли следующее?Измените конструктор класса case?

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) 

Возможно ли бесформенное или нам нужно идти по маршруту макроса?

ответ

7

Можно построить такой reshaper практически без изменений в вашем коде или пользовательских классах. Мы просто prepend списки аргументов, а затем align результат в 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

Спасибо! preend и align - это, безусловно, то, что вы ищете. – KailuoWang

Смежные вопросы