7

以下代码似乎足以编译和运行

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]。有任何想法吗?

4

1 回答 1

12

首先,我们可以创建一个Poly1类似的size,我们可以使用它来将 an 映射HList到 an HListof Strings

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

您已经使用Generic[Pair]将 aPair转换为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可以将 aPair转换为aHList 类型L
  • 我们的第二个隐式参数mapper可以使用我们的strings多态函数将一个HList类型映射L到一个HList类型M

我们现在可以funRun用来将 aPair变成HListof Strings

scala> funRun(Pair("abc", 12))
res1: shapeless.::[String,shapeless.::[String,shapeless.HNil]] = abc :: 12 :: HNil

但是你想返回一个List[String]. 要将我们的HList M(映射到 的结果String)转换为 aList[String]我们需要 a 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)
于 2015-09-08T09:34:33.353 回答