У меня есть следующий, часто цитируемый код для вычисления энного количества Фибоначчи в Haskell:стиля Non-pointfree значительно медленнее
fibonacci :: Int -> Integer
fibonacci = (map fib [0..] !!)
where fib 0 = 0
fib 1 = 1
fib n = fibonacci (n-2) + fibonacci (n-1)
Используя это, я могу сделать вызовы, такие как:
ghci> fibonacci 1000
и получите почти мгновенный ответ.
Однако, если я изменить код выше, так что это не в стиле pointfree, т.е.
fibonacci :: Int -> Integer
fibonacci x = (map fib [0..] !!) x
where fib 0 = 0
fib 1 = 1
fib n = fibonacci (n-2) + fibonacci (n-1)
это существенно медленнее. В той степени, в которой такой звонок, как
ghci> fibonacci 1000
висит.
Насколько я понимаю, эти два фрагмента кода были эквивалентны, но GHCi требует отличия. У кого-нибудь есть объяснение этого поведения?
Первое определение больше похоже на 'fibonacci = let k = map fib [0 ..] в \ x -> k !! x'. Вероятно, он разделяет список результатов, а не пересчитывает их каждый раз. – melpomene
Мм, поэтому я доволен, что это «совместное использование» (memoization), которое делает первый супер быстрый. Но зачем делать то же самое для второго? – MadMonty
Вы используете свой код в GHCI без оптимизации. Попробуйте скомпилировать обе функции с помощью '-O2' и посмотреть, достаточно ли GHC для решения вашей проблемы. – user2407038