primes
в вашем коде - это не функция, а константа в haskellspeak, известная как CAF .Если бы он принял параметр (скажем, ()
), вы бы вернули две разные версии одного и того же списка, если вызывали его дважды, но, поскольку это CAF, вы оба раза возвращали один и тот же список;
Как определение верхнего уровня ghci, primes
никогда не становится недоступным, поэтому заголовок списка, на который он указывает (и, следовательно, его хвост / остальная часть вычисления), никогда не собирается сборщиком мусора.Добавление параметра предотвращает сохранение этой ссылки, тогда список будет собираться мусором, так как (!!)
выполняет итерацию по нему, чтобы найти нужный элемент, а ваш второй вызов (!!)
вызовет повторение всего вычисления вместо простого обхода ужевычисляемый список.
Обратите внимание, что в скомпилированных программах отсутствует область верхнего уровня, как в ghci, и вещи собирают мусор, когда последняя ссылка на них исчезает, вполне вероятно, до выхода всей программы, CAF или нетЭто означает, что ваш первый вызов займет много времени, второй - нет, и после этого, «будущее вашей программы» больше не ссылается на CAF, память, которую занимает CAF, используется повторно.
простой пакет предоставляет функцию, которая принимает аргумент (в первую очередь, я бы сказал) именно по этой причине, поскольку перенос около половины терабайта простых чисел может оказаться не тем, что нужно.
Если вы хотите по-настоящему разобраться в этом, я рекомендую прочитать STGбумага .Он не включает в себя новые разработки в GHC, но делает большую работу по объяснению того, как Haskell отображает на сборку, и, как следствие, жесткости, как правило, пожираются строгостью.