i'm trying modify caseclassmerge example shapeless library merge non-null fields.
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))) } }
how modify merging logic in way non-null fields in second argument merged first argument?
you add own implicit merger implementation current scope, overriding standard merger:
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 = field[k](mv) // replace if value 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))
Comments
Post a Comment