在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
的定义中接受了相同的模式(m
和n
互换)。
在定义中
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
,它不是构造函数。因此,括号之间的部分不能被解析为模式。