我一直试图创建一个无限的斐波纳契列表,产生可以将前2个值作为参数的函数。
如果没有指定前两个值,可以像这样
fib = 1 : 1 : zipWith (+) fib (tail fib)
假设我想用5和6而不是1,1或0,1开始斐波那契序列,那么我将不得不改变上面的代码。但是当我试图制作一个惰性列表生成器,我可以在其中指定斐波那契序列的前2个值时,我很难过。我想出了这个但是没有用。
fib a b = a : b : zipWith (+) fib (tail fib)
问题很明显。我试图转换硬编码列表的使用。我该如何解决?
答案 0 :(得分:15)
怎么样
fib a b = fibs where fibs = a : b : zipWith (+) fibs (tail fibs)
?使用相同的方法,但参数范围很广。
我应该补充一点,以防你被
诱惑fib a b = a : b : zipWith (+) (fib a b) (tail (fib a b)) -- worth trying?
where fibs
版本确保只生成一个无限流。后者可能会为fib
的每次递归调用生成一个新流。编译器可能足够聪明地发现公共子表达式,但依靠这样的运气是不明智的。尝试ghci
中的两个版本,看看计算第1000个元素需要多长时间。
答案 1 :(得分:2)
最简单的方法是:
fib a b = a: fib b (a+b)
这源于Fibonacci系列的归纳定义:假设我们有一个函数可以从F i 开始产生Fibonacci数的流,给定F i 和˚F<子> i + 1的子>。这个功能看起来像什么?那么,给出F i ,并且如果我们可以的话,可以使用该函数计算流的其余部分以从F i + 1 开始产生Fibonacci数的流。提供F i + 1 和F i + 2 。给出了F i + 1 ,因此我们只需要算出F i + 2 。系列的定义给我们F i + 2 = F i + F i + 1 ,所以,那里。