如何获取Shapeless HList中的每个类型元素属于类型类的证据

时间:2015-11-10 04:37:53

标签: scala shapeless

我尝试过以下方法:

trait Evidence[H <: HList, T[_]] {}

object Evidence {
  implicit def HNilEvidence[T[_]] = new Evidence[HNil, T] {}
  implicit def HListEvidence[Head, Remaining <: HList, T[_]](implicit headEv: T[Head], remainingEv: Evidence[Remaining, T]) =
    new Evidence[Head :: Remaining, T] {}
}

只有当所有元素都与类型类匹配时,这才能正确地给出一个隐含的证据。

但是,当试图像这样使用它时(一个人为的例子):

def transform[A](a: A)(implicit ev: Evidence[A :: HNil, Ordering]) =
   { List(a,a).sorted }

这给出了错误

error: No implicit Ordering defined for A.

应根据Evidence[A :: HNil, Ordering]

的存在而存在

2 个答案:

答案 0 :(得分:1)

您无需定义自己的Evidence类型类。使用无形'ops.hlist.LiftAll

def transform[A](a: A)(implicit
                                     liftAll: LiftAll.Aux[Ordering, A :: HNil, Ordering[A] :: HNil],
                                     isHCons: IsHCons.Aux[Ordering[A] :: HNil, Ordering[A], HNil]): List[A] = {
  implicit val ordering: Ordering[A] = liftAll.instances.head
  List(a, a).sorted
}

答案 1 :(得分:0)

为什么不用LUB表达List的内容,只是在方法级别移动订购证据的请求?这里的类型类比特是误导性的,你所匹配的似乎是type,除非我错过了明显的,而不是类型类或类型族。

LUBConstraint因为这个原因已经存在于Shapeless中。

class Transformer[HL <: HList, T](list: T :: HL)(
  implicit val c: LUBConstraint[HL, T]
) {
  def transform(obj: List[T])(
    implicit ev: Ordering[T],
    toList: ToList[T :: HL, T]
  ): List[T] = (toList(list) ::: obj).sorted(ev.reverse)
}

我也不太明白为什么你需要A类型参数以及ALUB之间的关系。我已经为您添加了一个示例,只是为了说明一点,希望它足以向您展示如何组合事物。

val list = "test3" :: "test1" :: "test2" :: HNil
val listb = List("test5", "test4", "test6")
val transformer = new Transformer(list)

transformer.transform(listb) shouldEqual List(
  "test6",
  "test5",
  "test4",
  "test3",
  "test2",
  "test1"
)