2

Although this thread were available, I wasn't allowed to ask my question under the answers (due to reputation points) therefore I had to create a new question for that regard. (I am just new in stackoverflow :)

I didn't clearly understand one point regarding how following fibs function works

fibs :: [Integer]
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)

In this stackoverflow thread

nichijou has step by step explained below the thread here I quoted from nichijou:

at first, with fibs and tail fibs, we can get the 3rd:

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 ..

fibs :: [Integer]
fibs = 1 : 1 : zipWith (+) fibs (tail fibs)

Here my question is, after the second step how did we get rid of the duplicates in the list? I was expecting to see the second step should generate a list as

[1, 1, 2, 2, 3] 

same goes in the next step and so on...

AJF
  • 11,407
  • 2
  • 34
  • 59
  • 3
    We did not generate duplicates. Where do you see duplicates here? – Willem Van Onsem Jul 25 '19 at 12:44
  • Asking a new question is the right thing to do. You should avoid seeing the list as developing in "steps". When we refer to `fibs` in that definition, we really mean the whole list. The accepted answer is better at explaining this. – AJF Jul 25 '19 at 12:45
  • @WillemVanOnsem no duplicates in running code, it works completely fine but I was wondering how come there is no duplicates when I iterate the recursion myself. Now the answer clarified my mind, understood the process better. – Aydin Yasar Jul 25 '19 at 14:07

1 Answers1

7

Let's write this out with some more labels:

fibs :: [Integer]
fibs = 1 : 1 : sumft
 where sumft = zipWith (+) fibs tfi
       tfi = tail fibs

Then, the “starting step” is

           ╭── tfi ───────┈┄··
fibs : [1, 1, ?, ?, ...
              ╰── sumft ──┈┄··
tfi  : [1, ?, ?, ?, ... 
sumft: [2, ?, ?, ?,

Now, as the computation marches on, the runtime don't move anything or whatever, it merely tries to fill in ? signs with concrete values. Remember, everything in Haskell is immutable; when I write ? I just mean I don't know yet what the value there is, but in principle it's already predetermined.

In this case, the runtime knows that the first ? in fibs comes from the head of sumft, whose exact value is known by now:

           ╭─── tfi ──────┈┄··
fibs : [1, 1, 2, ?, ...
              ╰─◀ sumft ──┈┄··
tfi  : [1, ?, ?, ?, ... 
sumft: [2, ?, ?, ?,

Now, this 2 is also known in tfi:

           ╭──▶ tfi ──────┈┄··
fibs : [1, 1, 2, ?, ...
              ╰── sumft ──┈┄··
tfi  : [1, 2, ?, ?, ... 
sumft: [2, ?, ?, ?,

...and thus we can perform the next addition:

           ╭─── tfi ──────┈┄··
fibs : [1, 1, 2, ?, ...
              ╰── sumft ──┈┄··
tfi  : [1, 2, ?, ?, ... 
sumft: [2, 3, ?, ?,

So, another number, i.e. another element of sumft that, being part of fibs, can also be used there. But it still occurs at the same place relative to the head of sumft – i.e. after the 2.

           ╭─── tfi ──────┈┄··
fibs : [1, 1, 2, 3, ...
              ╰─◀ sumft ──┈┄··
tfi  : [1, 2, ?, ?, ... 
sumft: [2, 3, ?, ?,

That gets again used in tfi

           ╭──▶ tfi ──────┈┄··
fibs : [1, 1, 2, 3, ...
              ╰── sumft ──┈┄··
tfi  : [1, 2, 3, ?, ... 
sumft: [2, 3, ?, ?,

...and so on and so on.

leftaroundabout
  • 101,764
  • 3
  • 156
  • 291