遅延評価(無限リストと take)

無限リストを作成し、その結果から take 関数により取得しているのではない。

import Debug.Trace

take' n _      | n <= 0 =  trace ("[]") []
take' _ []              =  trace ("[]") []
take' n (x:xs)          =  trace (show x ++ " : take' ("++show n++"-1) xs")
                                 (x : take' (n-1) xs)

iterate' f x =  trace (show x ++ " : iterate' f (f " ++ show x ++")")
                      (x : iterate' f (f x))

iterate' は無限ループの再帰関数だが、データが読まれたときになって初めて動作し、値は要求されたその都度に返している。

Main> take' 5 (iterate' (1+) 0)
0 : iterate' f (f 0)
0 : take' (5-1) xs
1 : iterate' f (f 1)
1 : take' (4-1) xs
2 : iterate' f (f 2)
2 : take' (3-1) xs
3 : iterate' f (f 3)
3 : take' (2-1) xs
4 : iterate' f (f 4)
4 : take' (1-1) xs
[]
[0,1,2,3,4]

 *Main> take' 5 $ [0..]
0 : take' (5-1) xs
1 : take' (4-1) xs
2 : take' (3-1) xs
3 : take' (2-1) xs
4 : take' (1-1) xs
[]
[0,1,2,3,4]

コードと実際の動作が違っているようにも見える。