I am trying to implement a method that does parameterized folding on a HList provided by the caller. The HList can have any number of elements (> 0) of the same type.
val list = "a" :: "b" :: "c" :: HNil
def process[L <: HList](mul: Int, l: L) = {
object combine extends Poly2 {
implicit def work = at[String, (Int, L)] {
case (a, (b, acc)) => (b, (a * b) :: acc)
}
}
l.foldRight((mul, HNil))(combine)._2
}
process(3, list) // expecting to get aaa :: bbb :: ccc :: HNil
What I get is error about missing implicit: "could not find implicit value for parameter folder: shapeless.ops.hlist.RightFolder[L,(Int, shapeless.HNil.type),combine.type]". From this answer it is clear that compiler wants to see evidence that it can fold the HList.
However I cannot pass a RightFolder as an implicit parameter because Poly2 type is not known outside the method. And even if it were possible, the implicit parameter would only propagate further up the call stack. In fact I don't want the caller to even know whether the method performs folding, mapping, reduction or anything else. All it needs to provide is evidence that the HList is the right kind of HList. I assume the problem is in [L <: HList] which is not specific enough but I am not sure how to make it right.
The following code works as expected but it obviously does not encapsulate folding logic in a method:
val list = "a" :: "b" :: "c" :: HNil
object combineS extends Poly2 {
implicit def work[L <: HList] = at[String, (Int, L)] {
case (a, (b, acc)) => (b, (a * b) :: acc)
}
}
list.foldRight((3, HNil))(combineS)._2