为什么haskell解释器会给我这个解析错误



在Richard Bird的《使用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

上出现解析错误

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

因为定义函数的自变量必须是模式,也就是

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

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

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

12 `divide` 4

--当函数被调用时,所有可用的都是值,而不是它是如何获得的——你尝试的函数定义需要编译器对值进行因子分析,以检查它是否可以以给定的形式写入

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

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

在定义中

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

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

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

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

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

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

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

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

最新更新