Self-Assessment in Haskell Features

I am studying Haskell and I have the following expression on the Haskell Wiki that really puzzled me:

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

I can’t understand why this is working.

If I use the standard logic Currying (zipWith (+)) , it returns a function that takes a list as an argument and, in turn, returns another function that takes a different list as an argument and returns a list ( zipWith::(a -> b -> c) -> [a] -> [b] -> [c] ). Thus, fibs is a link to a list (which has not yet been rated), and (tail fibs) is the tail of the same (unvalued) list. When we try to evaluate ( take 10 fibs ), the first two elements are tied to 0 and 1 . In other words, fibs==[0,1,?,?...] and (tail fibs)==[1,?,?,?] . After the first addition is complete, fibs becomes [0,1,0+1,?,..] . Similarly, after the second addition we get [0,1,0+1,1+(0+1),?,?..]

  • Is my logic correct?
  • Is there an easier way to explain this? (any ideas from people who know what the Haskell complier does with this code?) (links and links are welcome)
  • True, this type of code only works because of lazy evaluation?
  • What grades happen when I do fibs !! 4 fibs !! 4 ?
  • Does this code mean that zipWith processes the elements first? (I think this should not be, but I do not understand why not)

EDIT2: I just found the above question and answered here . I'm sorry if I wasted any time.

EDIT: here is a more complicated case to understand (source: Project Euler forums ):

 filterAbort :: (a -> Bool) -> [a] -> [a] filterAbort p (x:xs) = if px then x : filterAbort p xs else [] main :: Int main = primelist !! 10000 where primelist = 2 : 3 : 5 : [ x | x <- [7..], odd x, all (\y -> x `mod` y /= 0) (filterAbort (<= (ceiling (sqrt (fromIntegral x)))) primelist) ] 

Note that all (\y -> x mod y /= 0)... How can I refer to x here DO NOT call infinite recursion?

+8
recursion haskell lazy-evaluation self-reference
source share
1 answer

I will evaluate for you:

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

FROM

 > zipWith f (a:as) (b:bs) = fab : zipWith f as bs > zipWith _ _ _ = [] > tail (_:xs) = xs > tail [] = error "tail" 

So:

  fibs = 0 : 1 : zipWith (+) fibs (tail fibs) ↪ fibs = 0 : 1 : ((+) 0 1 : zipWith (+) (tail fibs) (tail (tail fibs))) ↪ fibs = 0 : 1 : 1 : ((+) 1 1 : zipWith (+) (tail (tail fibs)) (taii (tail (tail fibs))))) ↪ fibs = 0 : 1 : 1 : 2 : ((+) 1 2 : zipWith (+) (tail (tail (tail fibs))) (tail (taii (tail (tail fibs)))))) ↪ fibs = 0 : 1 : 1 : 2 : 3 : ((+) 2 3 : zipWith (+) (tail (tail (tail (tail fibs)))) (tail (tail (taii (tail (tail fibs))))))) 

Etc. Therefore, if you pointed to this structure, it will cause each step of the fibs to be evaluated until an index is found.

Why is this effective? One word: exchange.

When fibs calculated, it grows on the heap, writing down values ​​that were computer. Later fibs allow you to reuse all previously calculated values ​​for fibs . Free memory!

What does sharing look like on the heap?

enter image description here

When you request an object at the end of the list, Haskell calculates the next value, writes it, and moves this self-regulation down the node.

The fact that this ends is crucial to laziness.

+15
source share

All Articles