在函数内部映射 HList
mapping over HList inside a function
下面的代码看起来很明显,可以编译 运行
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)
}
但是编译器说 "could not find implicit value for parameter mapper"。在我的用例中,我想映射一个 HList 以获取和 HList of String(s),然后将 HList of String(s) 转换为 Scala List[String]。有任何想法吗?
首先我们可以创建一个类似于 size
的 Poly1
,我们可以使用它来将 HList
映射到 Strings
的 HList
。
object strings extends Poly1 {
implicit def caseInt = at[Int](_.toString)
implicit def caseString = at[String](identity)
}
您已经使用 Generic[Pair]
将 Pair
变成 HList
,但您无法映射到 hp
,因为您的 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
多态函数将类型 L
的 HList
映射到类型 [=] 的 HList
34=].
我们现在可以使用 funRun
将 Pair
变成 Strings
的 HList
:
scala> funRun(Pair("abc", 12))
res1: shapeless.::[String,shapeless.::[String,shapeless.HNil]] = abc :: 12 :: HNil
但是你想要return一个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)
下面的代码看起来很明显,可以编译 运行
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)
}
但是编译器说 "could not find implicit value for parameter mapper"。在我的用例中,我想映射一个 HList 以获取和 HList of String(s),然后将 HList of String(s) 转换为 Scala List[String]。有任何想法吗?
首先我们可以创建一个类似于 size
的 Poly1
,我们可以使用它来将 HList
映射到 Strings
的 HList
。
object strings extends Poly1 {
implicit def caseInt = at[Int](_.toString)
implicit def caseString = at[String](identity)
}
您已经使用 Generic[Pair]
将 Pair
变成 HList
,但您无法映射到 hp
,因为您的 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
多态函数将类型L
的HList
映射到类型 [=] 的HList
34=].
我们现在可以使用 funRun
将 Pair
变成 Strings
的 HList
:
scala> funRun(Pair("abc", 12))
res1: shapeless.::[String,shapeless.::[String,shapeless.HNil]] = abc :: 12 :: HNil
但是你想要return一个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)