【问题标题】:Class X Takes Types ParametersX 类采用类型参数
【发布时间】:2013-11-25 17:24:43
【问题描述】:

阅读Parser Combinators 上这篇内容丰富、写得很好的文章,我看到了这段代码:

class DisParser[+A](left: Parser[A], right: Parser[A]) extends Parser[A] {
  def apply(s: Stream[Character]) = left(s) match {
    case res: Success => res
    case _: Failure => right(s)
  }
}

当我尝试编译这段代码时,我得到:

Parser.scala:19: error: class Success takes type parameters
    case res: Success => res
              ^
one error found

鉴于Parser的签名:

case class Success[+A](value: A, rem: Stream[Character]) extends Result[A]

如何更改case res: Success => res 行以给Success 一个正确的类型参数?

【问题讨论】:

    标签: scala parser-generator


    【解决方案1】:

    您使用的是哪个Success?这个(Success 来自 Parsers 包)还是这个(Success 来自 util)?两者都接受类型参数,所以你需要把它写成

    res @ Success(_, _) =>
    

    否则您将不得不处理擦除警告。

    【讨论】:

    • 我正在使用该文章中定义的Success。另外,我尝试了您的 case Success(_, _) => ... 示例,但得到了:error: '=>' expected but '(' found.
    • @KevinMeredith 你能发布你更新的代码吗?我写的应该是你用替换res: Success =>
    • 哦,我的错误是不包括@。我不知道那个符号是什么意思。是的,使用您的代码时,我不再收到以前的编译时错误。但是,我得到了一个新的编译时错误:scala:26: error: covariant type A occurs in contravariant position in type Parser[A] of value that def |(that: Parser[A]) = new DisParser(this, that) ^
    • @KevinMeredith 您应该使用该方法def |[AA >: A](that: Parser[AA]) 阅读 Scala 中的协变类型。让人大开眼界。
    • 谢谢,@wheaties。您的解决方案和评论更改解决了我的问题。我已经看过 Odersky 在 Scala 中关于协方差的 FP 讲座两次,并多次阅读这篇文章 (stackoverflow.com/questions/663254/…),但我还没有深入了解协方差。再多几次就可以了:)
    【解决方案2】:

    你的解析器应该返回一个Result[A]类型的值,正如它的类型定义所说(基本上,解析器是一个从字符流到解析结果的函数)。:

    trait Parser[+A] extends (Stream[Character]=>Result[A])
    

    所以你有两个选择:

    case res@Success(_,_) => res
    

    与返回的 case 类的变体匹配。

    case res:Success[_] => res.asInstanceOf[Success[A]]
    

    与返回的 type 匹配(使用 instanceof 操作)。这就是你必须强制转换的原因(你不能匹配没有类型标签值的类型参数,因为 JVM 会进行类型擦除)。

    在您的情况下两者都有效,在第一种情况下,您省略了类型参数(这就是您最初的错误所在)。在您尝试遵循@wheaties 的建议时,您在代码中的某个地方出现了语法错误,但这确实是最好的方法。

    【讨论】:

    • 第一个选项中的@ 是什么?
    • @ 是模式匹配的绑定符号。它将标识符 res(绑定到模式 Success(_, _))引入到匹配表达式的 rhs。
    • 谢谢。使用第一个选项时,我收到错误,显示为wheaties 帖子中的评论。
    猜你喜欢
    • 2012-10-04
    • 1970-01-01
    • 2019-01-27
    • 2023-01-20
    • 1970-01-01
    • 2022-01-09
    • 1970-01-01
    • 2016-04-16
    • 1970-01-01
    相关资源
    最近更新 更多