下面的代码似乎很明显可以编译和运行
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]。有任何想法吗?
最佳答案
首先我们可以创建一个 Poly1
类似于 size
我们可以用它来映射 HList
到 HList
的 Strings
.
object strings extends Poly1 {
implicit def caseInt = at[Int](_.toString)
implicit def caseString = at[String](identity)
}
您已经在使用
Generic[Pair]
转一个 Pair
成HList
,但您无法映射您的 hp
因为你的funrun
没有证据你可以映射它。我们可以通过使用隐式参数来解决这个问题。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
映射 HList
的多态函数类型 L
到 HList
类型 M
. 我们现在可以使用
funRun
转一个 Pair
成HList
的 Strings
:scala> funRun(Pair("abc", 12))
res1: shapeless.::[String,shapeless.::[String,shapeless.HNil]] = abc :: 12 :: HNil
但是你想返回一个
List[String]
.转我们的HList
M
(映射到 String
的结果)到 List[String]
我们需要一个 ToTraversable
,所以我们添加了第三个隐式参数: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)
关于scala - 在函数内映射 HList,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32447709/