Display via HList inside a function

The following code seems obvious enough to compile and run

case class Pair(a: String, b: Int) val pairGen = Generic[Pair] object size extends Poly1 { implicit def caseInt = at[Int](x => 1) implicit def caseString = at[String](_.length) } def funrun(p: Pair) = { val hp: HList = pairGen.to(p) hp.map(size) } 

but the compiler says, "Could not find an implicit value for the mapper parameter." In my use case, I want to map an HList to get both an HList from String (s) and then convert the HList of strings (strings) to Scala List [String]. Any ideas?

+5
source share
1 answer

First, we can create Poly1 , similar to size , which we can use to map an HList to an HList from Strings .

 object strings extends Poly1 { implicit def caseInt = at[Int](_.toString) implicit def caseString = at[String](identity) } 

You have already used Generic[Pair] to turn Pair into an HList , but you could not display it hp , because in your funrun there is no evidence that you can display over it. We can solve this 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 type L
  • Our second implicit parameter, mapper can use our polymorphic function Strings to map an HList type L to an HList type M

Now we can 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 List[String] . To turn our HList M (display result into String ) into List[String] , we need 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 

What we can use as:

 scala> pairToStrings(Pair("abc", 12)) res2: List[String] = List(abc, 12) 
+8
source

All Articles