为什么Haskell中的递归成语是“'n + 1'和'n'”而不是“'n'和'n-1'”?

时间:2010-05-06 21:35:41

标签: haskell recursion idioms

我正在通过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

这里有什么我想念的吗?或者只是风格问题?

5 个答案:

答案 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 = Z1 = 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