问题描述
下面的代码看起来很明显,可以编译和运行
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)
}
但编译器说找不到参数映射器的隐式值".在我的用例中,我想映射 HList 以获取 String(s) 的 HList,然后将 String(s) 的 HList 转换为 Scala List[String].有任何想法吗?
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?
推荐答案
首先我们可以创建一个类似于 size
的 Poly1
,我们可以用它来映射一个 HList
到 Strings
的 HList
.
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)
}
您已经在使用 Generic[Pair]
将 Pair
转换为 HList
,但是您无法映射您的 hp
因为在您的 funrun
中没有证据表明您可以对其进行映射.我们可以通过使用隐式参数来解决这个问题.
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)
- 我们的第一个隐式参数
gen
可以将Pair
转换为HList
L
类型. - 我们的第二个隐式参数
mapper
可以使用我们的strings
多态函数将L
类型的HList
映射到M
类型的HList
. - 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
.
我们现在可以使用 funRun
将 Pair
转换为 Strings
的 HList
:
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
但是你想返回一个List[String]
.要将我们的 HList
M
(映射到 String
的结果)转换为 List[String]
,我们需要一个ToTraversable
,所以我们添加了第三个隐式参数:
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
我们可以用作:
scala> pairToStrings(Pair("abc", 12))
res2: List[String] = List(abc, 12)
这篇关于在函数内映射 HList的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!