無限リストを作成し、その結果から 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]
コードと実際の動作が違っているようにも見える。