当你在无形中做这样的事情时,最好的地方是在
shapeless.ops
打字课。在这种情况下,因为你知道你的第二个类是第一个类的严格子集,
Intersection
足以得到你想要的。您需要将其设置为一个类型类,以便传入输入和输出类型,并让编译器推断中间内容。
trait Converter[A,B] {
def convert(a: A): B
}
object Converter {
def apply[A,B](implicit converter: Converter[A,B]) = converter
implicit def genericConverter[A, B, ARepr <: HList, BRepr <: HList](
implicit
genA: Generic.Aux[A,ARepr],
genB: Generic.Aux[B,BRepr],
intersection: shapeless.ops.hlist.Intersection.Aux[ARepr,BRepr,BRepr]
): Converter[A,B] =
new Converter[A,B]{def convert(a: A): B = genB.from(intersection(genA.to(a)))}
}
这可以按如下方式使用:
case class Foo(a: Int, b: Int, c: String)
case class Bar(a: Int, c: String)
val foo = Foo(1,2,"Three")
val bar: Bar = Converter[Foo, Bar].convert(foo)