键入不匹配java.io.Serializable和GenTraversableOnce

时间:2015-05-27 04:53:49

标签: scala parsing

我试图让解析器采用一系列冒号分隔的单词并将它们转换为数组。

这是SSCCE。

import util.parsing.combinator._

class Element {

  def getSuper() = "TODO"

}

class Comp extends RegexParsers with PackratParsers {
  lazy val element: PackratParser[Element] = (
    "foo") ^^ {
    s => new Element
  }

  lazy val list: PackratParser[Array[Element]] = (
    (element ~ ";" ~ list) | 
    element ~ ";") ^^ 
  {
    case a ~ ";" ~ b => Array(a) ++ b 
    case a ~ ";" => Array(a)
  }
}

object Compiler extends Comp {
  def main(args: Array[String]) = {
    println(parseAll(list, "foo; foo; foo;"))
  }
}

它没有工作,而且它没有编译,如果不是我不会问它。这是我收到的错误消息。有没有办法从Serializable转换为GenTraversableOnce?

~/Documents/Git/Workspace/Uncool/Scales$ scalac stov.scala
stov.scala:19: error: type mismatch;
 found   : java.io.Serializable
 required: scala.collection.GenTraversableOnce[?]
    case a ~ ";" ~ b => Array(a) ++ b
                                                    ^
one error found

1 个答案:

答案 0 :(得分:3)

我怀疑是|组合子。

(element ~ ";" ~ list)的类型为~[~[Element, String], Array[Element]]element ~ ";"的类型为~[Element, String]

因此,当在这些解析器上应用|组合子时,它返回Parser[U],其中UT[U >: T])的超类型。

此处T的类型为~[~[Element, String], Array[Element]]U的类型为~[Element, String]

因此Array[Element]String之间最具体的类型是Serializable。 在~[Element, String]Element之间Object。这就是为什么|的类型为~[Serializable, Object]

因此,在应用map操作时,您需要提供一个函数~[Serializable, Object] => U,其中UArray[Element],因为函数的返回类型为PackratParser[Array[Element]]

现在唯一可能的匹配是:

case obj ~ ser => //do what you want

现在您看到您在地图中尝试匹配的模式根本就是错误的。即使你返回一个空数组(只是为了编译它),你也会发现它在运行时会导致匹配错误。

那就是说,我建议首先分别映射每个组合器:

lazy val list: PackratParser[Array[Element]] =
    (element ~ ";" ~ list) ^^ {case a ~ ";" ~ b => Array(a) ++ b} |
    (element ~ ";") ^^ {case a ~ ";" => Array(a)}

但您正在寻找的模式已经使用rep组合器实现(您还可以查看repsep,但是您需要处理上一个;分开):

lazy val list: PackratParser[Array[Element]] = rep(element <~ ";") ^^ (_.toArray)