Skip to content

Instantly share code, notes, and snippets.

@joroKr21
Created October 30, 2020 23:18
Show Gist options
  • Save joroKr21/2d0b521c21320d6cabaa4b430b64762b to your computer and use it in GitHub Desktop.
Save joroKr21/2d0b521c21320d6cabaa4b430b64762b to your computer and use it in GitHub Desktop.
Simple conversions between case classes and sealed traits with Shapeless
object Test {
import shapeless._
import shapeless.labelled._
trait Convert[A, B] {
def apply(a: A): B
}
object Convert {
implicit def id[A]: Convert[A, A] = x => x
implicit def hnil[A]: Convert[A, HNil] = _ => HNil
implicit def cnil[B]: Convert[CNil, B] = _ => ???
implicit def hcons[R <: HList, Q <: HList, K, A, B](implicit
sel: ops.record.Selector.Aux[R, K, A],
a2b: Convert[A, B],
r2q: Convert[R, Q]
): Convert[R, FieldType[K, B] :: Q] =
r => field[K](a2b(sel(r))) :: r2q(r)
implicit def ccons[C <: Coproduct, D <: Coproduct, K, A, B](implicit
sel: ops.union.Selector.Aux[D, K, B],
a2b: Convert[A, B],
c2d: Convert[C, D],
inj: ops.coproduct.Inject[D, FieldType[K, B]]
): Convert[FieldType[K, A] :+: C, D] = {
case Inl(a) => inj(field[K](a2b(a)))
case Inr(c) => c2d(c)
}
implicit def generic[A, B, R, Q](implicit
lga: LabelledGeneric.Aux[A, R],
lgb: LabelledGeneric.Aux[B, Q],
r2q: Convert[R, Q]
): Convert[A, B] =
a => lgb.from(r2q(lga.to(a)))
}
final case class Foo(a: Int)
final case class Bar(a: Int, b: String)
final case class Baz(x: Foo, y: Long)
final case class Qux(z: Double, x: Bar, y: Long)
implicitly[Convert[Qux, Baz]]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment