问题
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 implicit value for parameter mapper". In my use case, I want to map over an HList to get and HList of String(s) and then convert the HList of String(s) into Scala List[String]. Any ideas?
回答1:
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 aPair
into anHList
of typeL
. - Our second implicit parameter
mapper
can use ourstrings
polymorphic function to map anHList
of typeL
to anHList
of typeM
.
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)
来源:https://stackoverflow.com/questions/32447709/mapping-over-hlist-inside-a-function