如果我有以下方法:
def f[T: Generic, U: Generic](t: T): U
Generic[T].to(t)
返回类型Generic[T]#Repr
,我认为这是某种HList类型的类型别名。
是否可以从HList
中选择成员并构建另一个HList
,我可以确信编译器的类型为Generic[U]#Repr
,然后可以用它来创建{{ 1}}使用U
吗?
我尝试了许多方法,但似乎在转圈。
答案 0 :(得分:2)
在Shapeless中执行此类操作时,最好的外观是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)