Я был немного удивлен переполнением стека GHC, если мне нужно получить значение большого списка, содержащего элементы, интенсивно использующие память.Я ожидал, что у GHC есть TCO, поэтому я никогда не столкнусь с такими ситуациями.
Чтобы упростить случай, рассмотрим следующие простые реализации функций, возвращающих числа Фибоначчи (взяты из HaskellWiki).Цель состоит в том, чтобы отобразить миллионное число.
import Data.List
# elegant recursive definition
fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
# a bit tricky using unfoldr from Data.List
fibs' = unfoldr (\(a,b) -> Just (a,(b,a+b))) (0,1)
# version using iterate
fibs'' = map fst $ iterate (\(a,b) -> (b,a+b)) (0,1)
# calculate number by definition
fib_at 0 = 0
fib_at 1 = 1
fib_at n = fib_at (n-1) + fib_at (n-2)
main = do
{-- All following expressions abort with
Stack space overflow: current size 8388608 bytes.
Use `+RTS -Ksize -RTS' to increase it.
--}
print $ fibs !! (10^6)
print . last $ take (10^6) fibs
print $ fibs' !! (10^6)
print $ fibs'' !! (10^6)
-- following expression does not finish after several
-- minutes
print $ fib_at (10^6)
Источник скомпилирован с ghc -O2
.
Что я делаю не так?Я бы хотел избежать перекомпиляции с увеличенным размером стека или другими конкретными параметрами компилятора.