无形-通用Repr类型操作

时间:2019-03-14 16:32:49

标签: scala shapeless

如果我有以下方法:

        def f[T: Generic, U: Generic](t: T): U

Generic[T].to(t)返回类型Generic[T]#Repr,我认为这是某种HList类型的类型别名。

是否可以从HList中选择成员并构建另一个HList,我可以确信编译器的类型为Generic[U]#Repr,然后可以用它来创建{{ 1}}使用U吗?

我尝试了许多方法,但似乎在转圈。

1 个答案:

答案 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)