这个Fibonacci序列函数是递归的吗?

时间:2010-10-20 17:45:10

标签: haskell recursion

考虑以下(Haskell)代码:

fib=0:1:zipWith (+) fib (tail fib)

同事试图断言这不是一个递归函数,因为fib只是一个用自己定义自己的列表,并且它与执行相同操作的函数有某种不同。我认为他吸烟了。

您怎么看?

9 个答案:

答案 0 :(得分:14)

使用zipWith的fibonacci定义不是递归函数,实际上没有涉及函数,fib是一个利用Haskell的惰性语义懒惰自定义的列表(数据)。从某种意义上说,你可以称之为递归列表或递归数据;但不是递归函数。

由于很少有编程语言有任何接近,所以可能很难绕过递归列表,但是你会注意到在Haskell中所有函数只需要一个参数。 fib不接受任何参数,因为它不是函数。由于没有涉及函数,因此无法使用递归函数。

你的同事不吸烟,他是开明的(如果这是你对启蒙的定义,那就是吸烟裂缝)。

答案 1 :(得分:11)

我的,这是一个微妙的术语区别的老鼠窝。什么是“这个”?

fib=0:1:zipWith (+) fib (tail fib)

它不是递归函数。它不是递归数据。这是一个递归定义。

正在定义什么?

fib

根据这个定义,fib是什么类型的东西?

[Integer]

整数列表(或者可能是任何旧数字内容的列表)。

fib是一个功能吗?不,这是一个清单。是fib递归定义的吗?是。如果我们用相同类型的非递归函数替换fib(例如zipWith),是否会\ f xs ys -> xs递归定义?是的,虽然它是一个不同的递归定义列表。

fib是循环列表吗?不是。“递归数据结构”是指“循环数据结构”吗?不是根据Hoare的论文“递归数据结构”:http://portal.acm.org/book_gateway.cfm?id=63445&type=pdf&bookpath=%2F70000%2F63445%2Fcb-p217-hoare.pdf&coll=&dl=&CFID=15151515&CFTOKEN=6184618

在类型设置中,“递归数据结构”意味着不超过或少于“递归定义类型的居民”。相应地"fred"是一个递归数据结构,即使它没有递归定义,实际上它也可以通过++之类的递归函数来处理。

短语“递归函数”表示“递归定义的函数”。短语“递归值”表示“递归定义的值”,例如存在于非严格语言中:严格的语言具有“值递归”问题。

如果您认为这很迂腐,请尝试在编程语言中以这种方式定义fib,然后您会发现“递归定义”的概念分为“定义”结构递归“(以停止的方式消耗数据)和”通过保护的核心运行定义“(以某种方式生成数据),fib属于后一种类型。在这种情况下,fib的生产力主要取决于zipWith的懒惰。当然,在Haskell设置中,你不需要担心任何这些东西来弄清楚什么是某种定义,只是想知道它是否有一半的实际工作机会。

答案 2 :(得分:9)

这是递归的。您可以判断,因为=的LHS上的名称也出现在RHS上。

然而不是一个功能。您可以告诉我,因为fib的类型不包含->

答案 3 :(得分:3)

您给出的示例是递归的。但斐波那契序列本质上并非如此。有iterative versions of the algorithm,甚至是explicit functions

答案 4 :(得分:3)

由于大多数答案支持您的同事关于功能部分:“fib 不是递归功能。”我想详细阐述Conor McBride在他的回答中暗示的递归部分。

fib提供的定义递归,它是 co-recursive

共同递归看起来很像递归,正如许多海报所指出的那样,定义的LHS也出现在RHS上。但没有基本情况。递归和核心运行“以相反的方向运行”。

fib的上述定义从初始值0和1开始,并从那里“向上”移动并继续前进。 另一方面,递归定义,比如(函数计算)第n个斐波纳契数

fib' 0 = 0
fib' 1 = 1
fib' n = fib' (n-1) + fib' (n-2)

从第n个数字“向下”走,直到它到达基本情况并停止。

我想这证明了这两点的破解头: - )


如需进一步阅读,请查看Corecursion上的维基百科文章及其中的链接。如果你能够得到它,Kees Doets和Jan van Eijck的 Haskell之路逻辑,数学和编程的第10章可能值得一看。

答案 5 :(得分:2)

他正处于破解状态 - 上述功能显然是递归的。

答案 6 :(得分:2)

除了这里的Haskell实现之外,Fibonacci数是由递归关系定义的序列。从数学上讲,每个术语都被定义为前面术语的函数。用数学语义打败他。

答案 7 :(得分:2)

为了使它成为递归函数,它需要既是递归函数又是函数。正如sepp2k所指出的那样,它显然是递归的,因为名称fib出现在=的两侧。也就是说,fib是根据自身定义的。

这是一个功能吗?不是根据它的类型。在haskell中,我们将0参数函数称为“数据”。所以fib的这个定义创建了一个递归数据结构,但不是一个递归函数。

答案 8 :(得分:-1)

虽然评论中的很多人都在争论定义是否是一个函数,但每个人似乎都认为它是递归的。

至于函数/非函数参数,在Haskell中,从程序员的角度来看,它并不重要!因为懒惰地评估函数和数据结构,所以返回值的无参数的值和函数是不可区分的。你拥有的是一个整数列表,懒惰和递归地评估。 fib同时是“整数列表”,“无参数返回整数列表的函数”,“无参数返回整数的函数列表”,以及“返回列表的无参数的函数列表”无参数的函数返回整数“。

老实说没关系。语言没有区分四者。类型理论没有区分四个(和无数其他:没有参数的函数返回任何一个是同样有效的,因为没有参数返回的函数,无限制)。无论你是否将fib称为“功能”,它都没有任何区别。

但它是递归的。