2016-07-21 14 views
1

Ich versuche, caseclassmerge Beispiel von Shapeless-Bibliothek zu ändern, nur Nicht-Null-Felder zusammenzuführen.Nicht-Null-Felder in zwei Fallklassen zusammenführen

object mergeSyntax { 
    implicit class MergeSyntax[T](t: T) { 
    def merge[U](u: U)(implicit merge: CaseClassMerge[T, U]): T = merge(t, u) 
    } 
} 

trait CaseClassMerge[T, U] { 
    def apply(t: T, u: U): T 
} 

object CaseClassMerge { 
    import ops.record.Merger 

    def apply[T, U](implicit merge: CaseClassMerge[T, U]): CaseClassMerge[T, U] = merge 

    implicit def mkCCMerge[T, U, RT <: HList, RU <: HList] 
    (implicit 
     tgen: LabelledGeneric.Aux[T, RT], 
     ugen: LabelledGeneric.Aux[U, RU], 
     merger: Merger.Aux[RT, RU, RT] 
    ): CaseClassMerge[T, U] = 
    new CaseClassMerge[T, U] { 
     def apply(t: T, u: U): T = 
     tgen.from(merger(tgen.to(t), ugen.to(u))) 
    } 
} 

Wie die Verbindungslogik in einer Art und Weise zu ändern, dass nur Nicht-Null-Felder im zweiten Argumente werden in das erste Argument zusammengeführt werden?

Antwort

1

Sie könnten Sie besitzen implizite Fusion Implementierung auf den aktuellen Bereich hinzufügen, das Überschreiben der Standard-Fusion:

object NotNullHListMerger { 
    import shapeless.labelled._ 
    import shapeless.ops.record.Merger 
    import shapeless.ops.record.Remover 

    implicit def notNullHListMerger[K, V, T <: HList, M <: HList, MT <: HList] 
    (implicit 
    rm: Remover.Aux[M, K, (V, MT)], 
    mt: Merger[T, MT] 
): Merger.Aux[FieldType[K, V] :: T, M, FieldType[K, V] :: mt.Out] = 
    new Merger[FieldType[K, V] :: T, M] { 
     type Out = FieldType[K, V] :: mt.Out 
     def apply(l: FieldType[K, V] :: T, m: M): Out = { 
     val (mv, mr) = rm(m) 
     val up = field[K](mv) 
     // Replace only if value is not null 
     val h = Option(up).getOrElse(l.head) 
     h :: mt(l.tail, mr) 
     } 
    } 
} 

import mergeSyntax._ 
import NotNullHListMerger._ 

case class Foo(i: Int, s: String, b: Boolean) 
case class Bar(b: Boolean, s: String) 

val foo = Foo(23, "foo", true) 
val bar = Bar(false, null) 

val merged = foo merge bar 
assert(merged == Foo(23, "foo", false)) 
Verwandte Themen