Проблема в том, что ваше определение
iter :: Int -> Double
iter 0 = 0.3
iter n = f $ iter (n-1)
пытается оценить в неправильном направлении. Развернув его за несколько шагов, мы получим
iter n = f (iter (n-1))
= f (f (iter (n-2)))
= f (f (f (iter (n-3))))
...
и весь стек вызовов от iter 1000000
до iter 0
должен быть построен, прежде чем что-либо можно будет оценить. Это было бы то же самое на строгом языке. Вы должны организовать это так, чтобы часть оценки могла проходить до повторения. Обычный способ - иметь параметр накопления, например
iter n = go n 0.3
where
go 0 x = x
go k x = go (k-1) (f x)
Затем добавление аннотаций строгости - в случае, если компилятор их еще не добавил - заставит работать бесперебойно без использования стека.
Вариант iterate
имеет ту же проблему, что и ваш iter
, только стек вызовов построен изнутри, а не снаружи, как у вас. Но поскольку iterate
строит свой стек вызовов наизнанку, более строгая версия iterate
(или модель потребления, где более ранние итерации выполняются раньше) решает проблему,
iterate' :: (a -> a) -> a -> [a]
iterate' f x = x `seq` (x : iterate' f (f x))
вычисляет iterate' f 0.3 !! 1000000
без проблем.