«Совместное использование» означает f x
повторное использование созданного x
; но с _Y g = g . g . g . g . ...
каждый g
вычисляет свой вывод заново (см. this и this).
В этом контексте версия с совместным доступом имеет гораздо худшее использование памяти, приводит к утечке места. 1 sup >
Определение _Y
отражает обычный эффект определения лямбда-исчисления для комбинатора Y, который имитирует рекурсию путем дублирования, в то время как истинная рекурсия относится к тому же (следовательно, общий) объект.
In
x = f x
(_Y g) = g (_Y g)
оба x
относятся к одному и тому же объекту, но каждый из (_Y g)
относится к эквивалентному, но отдельному объекту. Во всяком случае, это его намерение.
Конечно, благодаря ссылочной прозрачности в Haskell the language нет никаких гарантий в этом отношении. Но компилятор GHC действительно так себя ведет.
_Y g
- это распространенное подвыражение, и оно могло быть "исключено" компилятором, дав ему имя и повторно использовав этот именованный объект, разрушая всю его цель. Вот почему в GHC есть флаг «исключение общих подвыражений» -fno-cse
, который явно предотвращает это. Раньше вам приходилось использовать этот флаг для достижения желаемого поведения здесь, но теперь это не так. GHC больше не будет так агрессивно устранять распространенные подвыражения с более свежими (читай: несколько лет назад) версиями.
отказ от ответственности: я являюсь автором той части страницы, на которую вы ссылаетесь. Я надеялся на то, что обычно на вики-страницах будет взад-вперед, но этого так и не произошло, поэтому мои работы так не рецензировались. Либо никто не побеспокоил, либо он пройден (без серьезных ошибок). Кажется, что вики уже много лет заброшены.
1 Используемая функция g
,
(3:) . minus [5,7..] . foldr (\ (x:xs) ⟶ (x:) . union xs) []
. map (\ p ⟶ [p², p² + 2p..])
производит увеличивающийся поток всех нечетных простых чисел, заданный увеличивающимся потоком всех нечетных простых чисел. Чтобы получить простое число N
по значению, он потребляет свой входной поток, по крайней мере, до первого простого числа выше sqrt(N)
по значению. Таким образом, производственные очки даются примерно путем повторного возведения в квадрат, и всего в цепочке (или "башне") этих простых чисел имеется ~ log (log N)
таких g
функций. производителей, каждый из которых подлежит немедленной сборке мусора, причем самый младший из них производит свои простые числа с учетом только первого нечетного простого числа, 3
, известного априори.
А с двухэтапным _Y2 g = g x where { x = g x }
их было бы только два в цепочке, но только верхний сразу стал бы сборщиком мусора, как обсуждалось по указанной выше ссылке.
person
Will Ness
schedule
11.12.2018