为什么Haskell中有递归习语';n+;1';和';n'&引用;而不是",';n';和';n-1'&引用;?
我正在阅读Graham Hutton的Haskell书,在他的递归章节中,他经常在“n+1”上进行模式匹配,如: 为什么是这样,而不是以下内容:(1)在功能上似乎相同,(2)在理解递归发生的情况方面更直观:为什么Haskell中有递归习语';n+;1';和';n'&引用;而不是",';n';和';n-1'&引用;?,haskell,recursion,idioms,Haskell,Recursion,Idioms,我正在阅读Graham Hutton的Haskell书,在他的递归章节中,他经常在“n+1”上进行模式匹配,如: 为什么是这样,而不是以下内容:(1)在功能上似乎相同,(2)在理解递归发生的情况方面更直观: myReplicate2 0 _ = [] myReplicate2 n x = x : myReplicate2 (n-1) x 这里有我遗漏的东西吗?或者这只是风格的问题?在第一个函数中,这些是n+k模式(应该避免!)。这两个函数的作用相同,除了不匹配负数的n+k函数。但是,建议使用后
myReplicate2 0 _ = []
myReplicate2 n x = x : myReplicate2 (n-1) x
这里有我遗漏的东西吗?或者这只是风格的问题?在第一个函数中,这些是n+k模式(应该避免!)。这两个函数的作用相同,除了不匹配负数的n+k函数。但是,建议使用后一个函数,,如果您不想故意使用负数,则可以使用后一个函数。,因为n+k模式是按计划使用的
不,你没有遗漏任何东西,这确实是一个风格问题,但我很少在野外看到n+k模式。n+k模式只在n>=0时匹配。因此,在myReplicate1中,n+1模式将只匹配正数,而负n将导致非穷举模式异常。在myReplicate2中,负n将创建一个无限列表 换句话说,当您不希望模式匹配负数时,您可以使用n+k模式,但是使用一个防护将更清晰
myReplicate n x = take n (repeat x)
完成了,完成了DN+K模式也有不同的严格含义 例如:
f (n+1) = Just n
g n = Just (n-1)
f对其第一个参数是严格的,g不是。这对于n+k模式没有什么特别之处,但适用于所有模式。我认为其背后的思想是:我们可以为自然数(0,1,…)定义一种类型,如下所示:
data Natural = Z -- zero
| S Natural -- one plus a number; the next number; the "successor"
myReplicate1 Z _ = []
myReplicate1 (S n) x = x : myReplicate1 n x
0=Z
,1=sz
,依此类推。这个系统被称为Peano算术,它几乎是一个数学标准,是定义“数字”的起点。您可以继续将Integer
s定义为Natural
s的成对(-ish),依此类推
当您这样做时,使用模式匹配变得很自然,如下所示:
data Natural = Z -- zero
| S Natural -- one plus a number; the next number; the "successor"
myReplicate1 Z _ = []
myReplicate1 (S n) x = x : myReplicate1 n x
我认为(这只是一个猜测),
n+1
模式背后的想法是我刚才描述的机器版本。因此,n+1
就像模式sn
一样。如果你这样想,n+1
模式看起来很自然。这也清楚地说明了为什么我们有一个附带条件,即n>=0
。我们只能使用类型Natural
表示n>=0
,换句话说,这是一个样式问题,第一个样式已被弃用。:)事实上他们不一样。N+K模式将不匹配负数。哎哟,没想到!谢谢,塞普,我编辑了我的答案!非常有趣-我想我遗漏了一些东西(n>=0位)。这是一种奇怪的魔法行为。我觉得很有趣,反对删除它的理由之一是“一些哈斯克尔的书使用它”: