Since
mystery = 0 : 10 : map (+1) mystery
by the definitions of (!!)
and (:)
and map
it is the case that
mystery !! 0 = 0 -- pseudocode
mystery !! 1 = 10
mystery !! n | n > 1
= (0 : 10 : map (+1) mystery) !! n
= (10 : map (+1) mystery) !! (n-1)
= (map (1+) mystery) !! (n-2)
= 1 + (mystery !! (n-2))
and there's your answer.
An illustration:
-- 0 1 2 3 4 5 6 -- n
mystery = [0, 10, 1, 11, 2, 12, 3, ...
-- / / / / / -- (+1)
-- [0, 10, 1, 11, 2, ...
-- 0 1 2 3 4 -- n-2
so all this is, is each element being defined with the reference to a previous one, two positions prior.
Thus another way to write the same thing down, making the pairing up (nay zipping) explicit, is
mystery = 0 : 10 : zipWith (+) (repeat 1)
mystery
-- and in general,
-- map (f y) xs == zipWith f (repeat y) xs
Translated into an imperative pseudocode, the program
main = print mystery
is actually the same as
main :
a = 0
b = 10
print "["
while( True ) :
print a ,
print b ,
a += 1
b += 1
A principled approach to tackle such problems is to name all your interim entities, the inner thunks behind lazy data constructors (here, :
), as they come into being, forced into WHNF by the demands of lazy evaluation. Then the mystery disappears:
mystery = 0 : 10 : map (+1) mystery
= x1 : t1
where
x1 = 0
t1 = 10 : map (+1) mystery
= x2 : t2
where
x2 = 10
t2 = map (+1) mystery
= map (+1) (x1 : t1)
= x1 + 1 : map (1+) t1 -- by definition of map
= x3 : t3
where
x3 = x1 + 1 = 0 + 1 = 1
t3 = map (1+) t1 = map (1+) (x2 : t2)
= x2 + 1 : map (1+) t2 -- = x_{n} + 1 : ...
= x4 : t4 -- = x_{n+2} : ...
where
....
At no point do we get any function other than (1+)
in this reduction process, nor do we ever get more than one of them stacked up in a row.
All we get is xn := 1 + xn-2
, repeatedly, for all n
above 1
.