我正在通过Graham Hutton的Haskell书籍,在他的递归章节中,他经常在“n + 1”上进行模式匹配,如:
myReplicate1 0 _ = []
myReplicate1 (n+1) x = x : myReplicate1 n x
为什么而不是以下,(1)在功能上看起来相同,(2)在理解递归发生的事情方面更直观:
myReplicate2 0 _ = []
myReplicate2 n x = x : myReplicate2 (n-1) x
这里有什么我想念的吗?或者只是风格问题?
答案 0 :(得分:12)
第一个函数中有n + k个模式(应该避免!)。两个函数都做同样的事情,除了n + k之外没有匹配的负数。然而,建议使用后者,如果你不想故意使用负数,可以采用,因为n + k模式被归结为removed anyways。
所以不,你什么都不缺,这确实是风格问题,但我很少看到野外的n + k模式。
答案 1 :(得分:6)
我认为背后的想法是这样的:我们可以像这样定义自然数(0,1,......)的类型:
data Natural = Z -- zero
| S Natural -- one plus a number; the next number; the "successor"
0 = Z
,1 = S Z
,依此类推。这个系统被称为Peano算术,并且几乎是数学中的一个标准,作为“数字”实际定义的(起点)。您可以继续将Integer
定义为Natural
s的对(-ish),依此类推。
当你这样做时,使用这样的模式匹配就很自然了:
myReplicate1 Z _ = []
myReplicate1 (S n) x = x : myReplicate1 n x
我认为(并且只是猜测)n+1
模式背后的想法是我刚刚描述的机器版本。因此,n+1
应被视为模式S n
。如果你这样想,n+1
模式似乎很自然。这也清楚地说明了为什么我们有n >= 0
的边条件。我们只能使用n >= 0
类型代表Natural
。
答案 2 :(得分:3)
N + K模式也有不同的严格意义。
例如:
f (n+1) = Just n
g n = Just (n-1)
f对其第一个参数是严格的,g不是。这对于n + k模式来说并不特别,但适用于所有模式。
答案 3 :(得分:2)
n + k模式仅在n> = 0时匹配。所以在你的myReplicate1中,n + 1模式只匹配正数,负数n将导致非穷举模式异常。在myReplicate2中,负数n将创建一个无限列表。
所以换句话说,当你不希望模式与负数相匹配时,你可以使用n + k模式,但使用后卫会更清楚。
答案 4 :(得分:-4)
myReplicate n x = take n (repeat x)
完成并完成。 :d