我正在尝试执行以下操作,也就是说,每次将头传递给通用函数时,都要通过匹配头和尾的模式来递归处理HList
。
import shapeless._
trait MyTrait {
def myFunc[T](x: String => T): Boolean
def iter(myHList: HList, acc: List[Boolean]): List[Boolean] = {
myHList match {
case HNil => acc
case head :: tail => myFunc(head) :: iter(tail, acc)
}
}
}
问题是我从匹配中得到的头部类型为Any
,而不是我放入HList
中的头部类型。我希望将head作为参数的函数具有正确的类型参数T
。
这可能吗?也许除了Shapeless以外还有其他方法吗?
答案 0 :(得分:0)
尝试
def iter(myHList: HList, acc: List[Boolean]): List[Boolean] = {
(myHList: @unchecked) match {
case HNil => acc
case (head: Function1[String, _] @unchecked) :: tail =>
myFunc(head) :: iter(tail, acc)
}
}
(第一个@unchecked
禁止警告模式匹配不完整,第二个@unchecked
禁止警告由于类型擦除而导致未经检查的通用String
)。
或者,您可以更安全地匹配类型。但是通常写一个参数只是一个HList
而不是一个特定的A :: B :: ... :: HNil
太粗糙了。由于您的函数对不同类型的值(即HNil
和H :: T
)的作用不同,因此它是Poly
。
object iter extends Poly2 {
implicit val nilCase: Case.Aux[HNil, List[Boolean], List[Boolean]] =
at((_, acc) => acc)
implicit def consCase[A, T <: HList](implicit
tailCase: Case.Aux[T, List[Boolean], List[Boolean]]
): Case.Aux[(String => A) :: T, List[Boolean], List[Boolean]] =
at { case (head :: tail, acc) => myFunc(head) :: iter(tail, acc) }
}
用法:
def myFunc[T](x: String => T): Boolean = true
iter(((s: String) => s.toUpperCase) :: ((s: String) => s.length) :: HNil, List[Boolean]())
// List(true, true)