简体   繁体   中英

How to get evidence that each type element in Shapeless HList belongs to a typeclass

I've tried the following:

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] {}
}

This correctly gives me an implicit evidence, only when all elements match a typeclass.

But, when trying to use it like this (a contrived example):

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

this gives the error

error: No implicit Ordering defined for A.

which should be there based on presence of Evidence[A :: HNil, Ordering]

Why not express the contents of the List with an LUB and simply move the request for ordering evidence at the method level? The typeclass bit here is misleading, what you are matching seems to be a type unless I'm missing the obvious, not a type-class or a type-family.

LUBConstraint already exists in Shapeless for this reason.

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)
}

I also don't really understand why you need the A type param and what the relation is between A and the LUB . I've added an example for you just to make a point, hopefully it's useful enough to show you how to combine things.

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"
)

You don't need to define your own Evidence type class. Use shapeless' 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
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM