【问题标题】:Scala: recursively pattern match a heterogeneous list, obtaining the correct type of each elementScala:递归模式匹配异构列表,获取每个元素的正确类型
【发布时间】:2018-12-11 04:44:19
【问题描述】:

我正在尝试做类似下面的事情,即通过模式匹配头部和尾部来递归处理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之外还有其他方法?

【问题讨论】:

标签: scala generics generic-programming shapeless


【解决方案1】:

试试

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 太粗糙了。由于您的函数对不同类型的值(即HNilH :: 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)

【讨论】:

    猜你喜欢
    • 2014-08-20
    • 2013-06-08
    • 2015-05-30
    • 1970-01-01
    • 2015-09-12
    • 2019-04-20
    • 1970-01-01
    • 2011-10-05
    • 2020-12-28
    相关资源
    最近更新 更多