On Monday den 3. December 2012 at 21.38, Brent Yorgey wrote:
On Mon, Dec 03, 2012 at 08:10:00PM +0100, Christoffer Buchholz wrote:All right, thanks for clearing up my misconceptions!I'm trying to understand, but I still don't think I do. Any idea howI can get to understand it?Think about it hard. Read a lot. Play with some examples. Askquestions.When I look at your "illustration" where you named the parts, itdoes seem more clear, but I don't get how e.g. at the third number`(tail f)` equals f'' equals 1? f'' clearly equals 1, but `(tail f)`would equal 1:1, wouldn't it? Same at the fourth number, f'' clearlyequals 2, but `(tail f)` would equal 1:1:2, wouldn't it? Or am Imisunderstand what `f`?No, inf = 0 : f'@(1 : f''@(1 : zipWith (+) f' f''))I mean thatf' = 1 : 1 : zipWith (+) f' f''andf'' = 1 : zipWith (+) f' f''Also, note that 'tail f' cannot be 1:1:2, since that does not eventype check. It is 1:1:2:<some unevaluated expression>, where inparticular the unevaluated expression involves zipWith and refers backto f' and f''.-BrentOn Monday den 3. December 2012 at 16.31, Brent Yorgey wrote:Hi Chris,On Mon, Dec 03, 2012 at 04:05:28PM +0100, Christoffer Buchholz wrote:HiI have been looking at this fibonacci implementation:f = 0:1:(zipWith (+) f (tail f))and I have been trying to fit it inside my head. I am not quite there yet, though.And it is easy to see that it works, but what I do not understand is how the two recursive applications progress. How do they evolve concurrently? For each execution of `f`, `f` will be executed twice. So how does all these results end up in the same list?f is not 'executed'. And it certainly is not executed twice for eachexecution, or anything like that.f is simply a *name* for an *expression*. All three occurrences of fin the code above refer to the *same* expression. They do not "evolveconcurrently", they simply *are* the same thing. Operationally, theyare all represented by pointers to the exact same list structure inmemory. Note also that simply referring to an expression does not'do' anything; when I said 'Hi Chris' above, it did not cause you tobe 'executed'. I simply referred to you, and you went on being thesame person you were all along.The thing to think about is not execution but the *process ofevaluation*. Unlike people, Haskell expressions can be partiallyevaluated, and the process of evaluation happens on demand.Unfortunately it is very difficult to show the process of evaluationin an email because for this expression it really requires thinkingabout the expression as a *graph*, and those are hard to draw in anemail.At first f looks like this:f = 0 : 1 : zipWith (+) f (tail f)Now, if we demand to know the next element of the list, we need toevaluate the call to zipWith. zipWith, in turn, demands to know thefirst elements of its arguments. Well, we can see that the firstelement of f is 0, and the first element of (tail f) is 1. So thenext element of the list is (0+1) = 1. At this point f looks likethis:f = 0 : f'@(1 : f''@(1 : zipWith (+) f' f''))Here's where a picture would be really helpful. Instead of drawing agraph I have given certain parts of the expression names. You can seethat the arguments to zipWith are really just pointers back tosubexpressions of f itself. Continuing, the next step would look likethis:f = 0 : 1 : f'@(1 : f''@(2 : zipWith (+) f' f''))And so on.I hope that was at least somewhat helpful, though I suspect you willprobably still be confused. That's OK though; embrace the confusionand keep asking questions. =)-Brent_______________________________________________Beginners mailing listBeginners@haskell.org (mailto:Beginners@haskell.org)