在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
答案 0 :(得分:3)
您在
上遇到解析错误(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
两次,但任何变量标识符只能在模式匹配中出现一次。
请注意
m
的定义中接受了相同的模式(n
和times
互换)。
在定义中
m `times` Succ n = (m `times` n) `plus` m
函数times
是为某些类型的参数定义的。整个左侧不是模式,我们有两个模式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
,它不是构造函数。因此,括号之间的部分不能被解析为模式。