Last active
December 2, 2020 11:37
-
-
Save milessabin/c3c9fbc57b1d913c2ee4 to your computer and use it in GitHub Desktop.
Merging arbitrary case classes via shapeless ... (LabelledGeneric and record merge).
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import shapeless._ | |
object CaseClassMergeDemo extends App { | |
import mergeSyntax._ | |
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, "bar") | |
val merged = foo merge bar | |
assert(merged == Foo(23, "bar", false)) | |
} | |
// Implementation in terms of LabelledGeneric ... | |
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))) | |
} | |
} |
No worries. Thanks for getting back to me and not pulling a https://xkcd.com/979/.
lol, you're welcome!
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
No, to tell the truth I asked out of curiosity when I started studying shapeless but didn't need to accomplish that task so I didn't delve into accomplishing that.