Given two case class
es:
case class Foo(x: Int)
case class Bar(x: Int)
Using shapeless
, how can I determine if Foo
and Bar
have the same "shape", i.e. Int :: HNil
is HList
?
A
, B
have same shape if there exists a shape S
such that S
is the generic representation of both A
and B
. This translates directly into the following function:
trait SameShape[A, B]
object SameShape {
implicit def instance[A, B, S]
(implicit a: Generic.Aux[A, S], b: Generic.Aux[B, S]): SameShape[A, B] =
new SameShape[A, B] {}
}
For specific case classes you can just do:
case class Foo(x: Int)
case class Bar(x: Int)
case class Baz(x: String)
implicitly[Generic.Aux[Foo, Int :: HNil]]
implicitly[Generic.Aux[Bar, Int :: HNil]]
implicitly[Generic.Aux[Baz, String :: HNil]]
More general approach:
If you prefer to work with values you can create function:
def test[A, B, L <: HList](a: A, b: B)(implicit
gen1: Generic.Aux[A, L],
gen2: Generic.Aux[B, L]): Int = 42
val foo = Foo(1)
val bar = Bar(2)
val baz = Baz("a")
test(foo, bar) // compiles
// test(foo, baz) // doesn't compile
If you prefer to work with types you can create type class:
trait SameShape[A, B]
object SameShape {
implicit def mkSameShape[A, B, L <: HList](implicit
gen1: Generic.Aux[A, L],
gen2: Generic.Aux[B, L]
): SameShape[A, B] =
new SameShape[A, B] {}
}
implicitly[SameShape[Foo, Bar]] // compiles
// implicitly[SameShape[Foo, Baz]] // doesn't compile
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With