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]
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
}
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"
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With