First we can create a Poly1 similar to size which we can use to map an HList to an HList of Strings.
object strings extends Poly1 {
implicit def caseInt = at[Int](_.toString)
implicit def caseString = at[String](identity)
}
You were already using Generic[Pair] to turn a Pair into an HList, but you couldn't map over your hp because there is no evidence in your funrun that you can map over it. We can solve this by using implicit parameters.
def funRun[L <: HList, M <: HList](
p: Pair
)(implicit
gen: Generic.Aux[Pair, L],
mapper: Mapper.Aux[strings.type, L, M]
) = gen.to(p).map(strings)
- Our first implicit parameter
gen can turn a Pair into an HList
of type L.
- Our second implicit parameter
mapper can use our strings polymorphic function to map an HList of type L to an HList of type M.
We can now use funRun to turn a Pair into an HList of Strings :
scala> funRun(Pair("abc", 12))
res1: shapeless.::[String,shapeless.::[String,shapeless.HNil]] = abc :: 12 :: HNil
But you wanted to return a List[String]. To turn our HList M (the result of mapping to String) to a List[String] we need a ToTraversable, so we add a third implicit parameter :
import shapeless._, ops.hlist._
def pairToStrings[L <: HList, M <: HList](
p: Pair
)(implicit
gen: Generic.Aux[Pair, L],
mapper: Mapper.Aux[strings.type, L, M],
trav: ToTraversable.Aux[M,List,String]
): List[String] = gen.to(p).map(strings).toList
Which we can use as :
scala> pairToStrings(Pair("abc", 12))
res2: List[String] = List(abc, 12)