【问题标题】:why is haskell interpreter giving me this parse error?为什么haskell解释器给我这个解析错误?
【发布时间】:2012-12-01 22:33:49
【问题描述】:

在 Richard Bird 的书“Introduction to Functional Programming Using Haskell”第二版中做练习。在以下代码的最后一行,我得到了错误:

"Parse error in pattern (n `times` Succ m)

请注意,times 的定义中接受了相同的模式(m 和 n 互换)。为什么会出现此错误?

    data Nat = Zero | Succ Nat
    deriving (Eq, Ord, Show)

    plus :: Nat -> Nat -> Nat
    m `plus` Zero = m
    m `plus` Succ n = Succ (m `plus` n)

    m `times` Zero = Zero
    m `times` Succ n = (m `times` n) `plus` m

    divide :: Nat -> Nat -> Nat
    Zero `divide` m = Zero
    (n `times` Succ m) `divide` n = Succ m

【问题讨论】:

  • 提示:我猜 Richard Bird 先生希望您“除”一个忽略余数的总函数(当然,n 除零除外)。

标签: haskell pattern-matching parse-error


【解决方案1】:

你得到一个解析错误

(n `times` Succ m) `divide` n = Succ m

因为定义函数的参数必须是模式,即

  • 通配符_
  • 变量标识符foo
  • 构造函数应用程序(一个值构造函数应用到其数量要求的任意多的模式)
  • 标签模式F{field1 = value1, ..., fieldN = valueN}(如果构造函数F是使用命名字段语法定义的)
  • 文字 1, "foo"
  • 否定文字-1
  • 元组模式,(1,2)
  • 列表模式[1,2]
  • 带括号的模式(pat),其中pat 是一个模式
  • 一个惰性模式,~pat,其中pat 是一个模式

这里的第一个参数不是模式,而是非构造函数的函数应用。

模式允许解构一个值,但普通函数应用程序不允许。对于你的问题,如果你有

12 `divide` 4

——调用函数时可用的只是值,而不是获取方式——您尝试的函数定义将要求编译器考虑该值以检查它是否可以以给定的形式写入。

该行中的另一个问题是您使用了标识符n 两次,但任何变量标识符在模式匹配中只能出现一次。

请注意,times 的定义中接受了相同的模式(mn 互换)。

在定义中

m `times` Succ n = (m `times` n) `plus` m

函数times 是为某些类型的参数定义的。整个左侧不是模式,我们有两个模式 m - 一个匹配每个参数并将其绑定到名称 m 的变量模式 - 和 Succ n(包含嵌套变量模式 @987654345 @)。

定义的左侧由定义的名称 (times) 和两个参数模式组成。

divide 的定义中,需要相同的结构、要定义的名称以及参数的两种模式。

(n `times` Succ m) `divide` n = Succ m

因此,当解析器遇到左括号时,它需要一个带括号的模式。但它发现

     n          `times`            Succ m
pattern infix-function-application pattern

那个表达式树的顶部节点是times,它不是构造函数。因此,括号之间的部分不能被解析为模式。

【讨论】:

  • 感谢您的周到和详细的回答。
猜你喜欢
  • 2021-11-06
  • 1970-01-01
  • 2021-05-24
  • 1970-01-01
  • 1970-01-01
  • 2020-04-17
  • 2014-09-15
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多