module HaskellEval where

doITerminate = take 2 (from 0)
  where
    from i = i : from (i + 1)

doIEvenMakeSense = take 2 zs
  where
    zs = 0 : zs
    -- At low level this is one node pointing back to itself. O(1)-space.


cubeRoot b = within 0.001 (iterate next b)
    -- From the standard library:
    -- iterate f z = z : iterate f (f z)
    --             = [z, f z, f (f z), f (f (f z)), ...]
  where
    next x = (2*x + b/x^2) / 3
    within eps (x : x1 : rest)
        | abs (x - x1) <= eps = x1
        | otherwise = within eps (x1 : rest)


mySumV2 xs = g 0 xs
  where
    g accum [] = accum
    g accum (x:xs) = g (accum + x) xs

mySumV1 [] = 0
mySumV1 (x:xs) = x + mySumV1 xs

mySumV3 xs = g 0 xs
  where
    g accum [] = accum
    g accum (x:xs) = seq accum (g (accum + x) xs)
    -- Note: accum is something that "g (accum + x) xs" will need.

mySumV4 xs = g 0 xs
  where
    g accum (x:xs) = let a1 = accum + x
                     in seq a1 (g a1 xs)
    -- Note: a1=accum+x is something that "g a1 xs" will need.