Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Haskell Fibonacci Explanation

I am quite new to Haskell and I'm trying to wrap my head around how the lazy expression of Fibonacci sequences work.

I know this has been asked before, but none of the answers have addressed an issue I'm having with visualising the result.

The code is the canonical one using zipWith

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

I understand the following:

  1. zipWith literally zips two lists together
  2. tail grabs all but the first element of a list
  3. Haskell references 'to-be' computed data as thunks.

From my understanding, it first adds [0,1,<thunk>] and [1,<thunk>] using zipWith (+) to give [1,<thunk>]. So now you have

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

A lot of references I've Googled have then proceeded to "visualise" the line above as

fibs = 0 : 1 : 1 : zipWith (+) [1,1,<thunk>] ([1,<thunk>]).

My question is this:

Why is the fibs component in the line above only corresponding to [1,1,<thunk>] instead of [0,1,1,<thunk>]?

Shouldn't fibs contain the entire list plus <thunk>?

like image 685
MikamiHero Avatar asked Nov 10 '14 12:11

MikamiHero


People also ask

Is there an algorithm for the Fibonacci sequence in Haskell?

@Zelphir: that would require readers to also be familiar with the golden ratio. Preciseness isn't critical to this argument There are a number of different Haskell algorithms for the Fibonacci sequence here. The "naive" implementation looks like what you're after. fibs : [1, 1, ? tail fibs : [1, ? zipWith (+) fibs (tail fibs): [2, ?

How to calculate the nth Fibonacci number?

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)

What is a Fibonacci sequence?

Fibonacci Sequence (Definition, Formulas and Examples) Fibonacci sequence is defined as the sequence of numbers and each number equal to the sum of two previous numbers. Visit BYJU’S to learn definition, formulas and examples.

How do you calculate the Fibonacci series?

There is an alternative Haskell definition for the Fibonacci serie, which would be easier to analyze I think: | fibSerie a b = a : (fibSerie b (a+b)) and then: fibs = fibSerie 1 1. ω = 2 + min ω (ω - 1). zipWith produces an (infinite) list of integers here, not just one integer, so it's not 2 + 1 overall elements, but 2 + ω. which is ω.


2 Answers

This intermediate step is wrong because zipWith has already processed the first pair of items:

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

Recall what zipWith does in the general case:

zipWith f (x:xs) (y:ys) = (f x y) : zipWith f xs ys

If you apply the definition directly you get this expansion:

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)                # fibs=[0,1,...]
     = 0 : 1 : zipWith (+) [0,1,...] (tail [0,1,...])      # tail fibs=[1,...]
     = 0 : 1 : zipWith (+) [0,1,...] [1,...]               # apply zipWith
     = 0 : 1 : (0+1 : zipWith (+) [1,0+1,...] [0+1,...])   
     = 0 : 1 : 1 : zipWith (+) [1,1,...] [1,...]           # apply zipWith
     = 0 : 1 : 1 : (1+1 : zipWith (+) [1,1+1,...] [1+1,...])
     = 0 : 1 : 1 : 2 : zipWith (+) [1,2,...] [2,...]       # apply zipWith
     = 0 : 1 : 1 : 2 : (1+2 : zipWith (+) [2,1+2,...] [1+2,...])
     = 0 : 1 : 1 : 2 : 3 : zipWith (+) [2,3...] [3,...]    # apply zipWith
     :
like image 78
Joni Avatar answered Oct 13 '22 09:10

Joni


How to visualize what's going on.

  1 1 2 3  5  8 13 21 ...   <----fibs
  1 2 3 5  8 13 21 ...      <----The tail of fibs
+_________________________  <----zipWith (+) function
  2 3 5 8 13 21 34 ...

 Finally, add [1, 1] to the beginning
 1, 1, 2, 3, 5, 8, 13, 21, 34, ...
like image 2
Nick Ziebert Avatar answered Oct 13 '22 10:10

Nick Ziebert