Generating Fibonacci numbers in Haskell?
Solution 1:
Here's a different and simpler function that calculates the n'th Fibonacci number:
fib :: Integer -> Integer
fib 0 = 0
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
The implementation you are referring to relays on some observations about how values in Fibonacci relate to each other (and how Haskell can define data structures in terms of themselfs in effect creating infinite data structures)
The function in your question works like this:
Assume you already had an infinite list of the Fibonacci numbers:
[ 1, 1, 2, 3, 5, 8, 13, .... ]
The tail
of this list is
[ 1, 2, 3, 5, 8, 13, 21, .... ]
zipWith
combines two lists element by element using the given operator:
[ 1, 1, 2, 3, 5, 8, 13, .... ]
+ [ 1, 2, 3, 5, 8, 13, 21, .... ]
= [ 2, 3, 5, 8, 13, 21, 34, .... ]
So the infinite list of Fibonacci numbers can be calculated by prepending the elements 1
and 1
to the result of zipping the infinite list of Fibonacci numbers with the tail of the infinite list of Fibonacci numbers using the +
operator.
Now, to get the n'th Fibonacci number, just get the n'th element of the infinite list of Fibonacci numbers:
fib n = fibs !! n
The beauty of Haskell is that it doesn't calculate any element of the list of Fibonacci numbers until its needed.
Did I make your head explode? :)
Solution 2:
going by the definition, every item of the fibonacci series is the sum of the previous two terms. putting this definition in to lazy haskell gives u this!
fibo a b = a:fibo b (a+b)
now just take n items from fibo starting with 0,1
take 10 (fibo 0 1)
Solution 3:
To expand on dtb's answer:
There is an important difference between the "simple" solution:
fib 0 = 1
fib 1 = 1
fib n = fib (n-1) + fib (n-2)
And the one you specified:
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
The simple solution takes O(1.618NN) time to compute the Nth element, while the one you specified takes O(N2). That's because the one you specified takes into account that computing fib n
and fib (n-1)
(which is required to compute it) share the dependency of fib (n-2)
, and that it can be computed once for both to save time. O(N2) is for N additions of numbers of O(N) digits.
Solution 4:
There are a number of different Haskell algorithms for the Fibonacci sequence here. The "naive" implementation looks like what you're after.
Solution 5:
fibs :: [Integer]
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)
at first, with fibs
and tail fibs
, we can get the 3rd element:
fibs : [1, 1, ?
tail fibs : [1, ?
zipWith (+) fibs (tail fibs): [2, ?
now, we know the 3rd is 2, we can get the 4th:
fibs : [1, 1, 2, ?
tail fibs : [1, 2, ?
zipWith (+) fibs (tail fibs): [2, 3, ?
now the 5th:
fibs : [1, 1, 2, 3, ?
tail fibs : [1, 2, 3, ?
zipWith (+) fibs (tail fibs): [2, 3, 5, ?
and so on ..