匹配类型的头/尾模式匹配参数

时间:2015-11-02 10:42:39

标签: scala pattern-matching

我正在处理Ninety-Nine Scala Problems的问题P07:

P07 (**) Flatten a nested list structure.
Example:
scala> flatten(List(List(1, 1), 2, List(3, List(5, 8))))
res0: List[Any] = List(1, 1, 2, 3, 5, 8)

我最初尝试解决方案是:

def flatten[A](ls : List[A]): List[A] = {
   def flattenRec[A](ls: List[A], flatList: List[A]): List[A] = ls match {
     case Nil => flatList
     case head: List[A] :: tail =>  flattenRec(head ::: flatten(tail), flatList)
     case head :: tail => flattenRec(tail, flatList :+ head)
   }
   flattenRec(ls, List[A]())
 }

但是这并没有编译,因为我不允许在第二个head语句中为case指定类型。我有办法做到这一点吗?

另外,推荐的解决方案使用flatMap代替match,但我不确定为什么在这种情况下甚至需要模式匹配...

2 个答案:

答案 0 :(得分:5)

您可以将头部声明括起来:

def flatten[A](ls : List[A]): List[A] = {
  def flattenRec[A](ls: List[A], flatList: List[A]): List[A] = ls match {
    case Nil => flatList
    case (head: List[A]) :: tail => flattenRec(head, flatList)
    case head :: tail => flattenRec(tail, flatList :+ head)
  }
  flattenRec(ls, List[A]())
}

请注意,您将收到有关未选中的类型模式的警告(因为头部需要是A的列表而不是其他任何内容的事实将在运行时由于擦除而丢失),您将需要向自己保证你可以忽略(或者通过涉及TypeTag s的一些hijink)。

答案 1 :(得分:0)

不错的问题和下面的替代解决方案:

def flatten(a:List[Any]):List[Any] = 
   a.flatMap{
      case l:List[Any] => flatten(l)
      case l => List(l)
   }