«Обмен» означает, что f x
повторно использует x
, который он создает;но с _Y g = g . g . g . g . ...
каждый g
вычисляет свой вывод заново (ср. this и this ).
В этом контексте версия для совместного использования имеет гораздо худшие значенияиспользование памяти приводит к утечке пространства . 1
Определение _Y
отражает обычный эффект определения лямбда-исчисления для Y комбинатор, который эмулирует рекурсию путем дублирования, в то время как истинная рекурсия относится к той же (следовательно, shared ) сущности.
В
x = f x
(_Y g) = g (_Y g)
оба x
относятся к той же сущности, но каждая из (_Y g)
относится к эквивалентной, но отдельной сущности.Во всяком случае, это и есть намерение.
Конечно, благодаря прозрачности ссылок, в Haskell языке нет никаких гарантий для всего этого.Но 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)
, по крайней мере.Таким образом, производственные точки даются примерно путем повторного возведения в квадрат, и в цепочке (или "башня" ) из этих * 1076 имеется в общей сложности ~ log (log N)
таких функций.* Производители простых чисел , каждый из которых подлежит немедленному сбору мусора, самый низкий из них производит свои простые числа с учетом только первого нечетного простого числа, 3
, известного априори.
И с двухэтапным _Y2 g = g x where { x = g x }
в цепочке будет только два из них, но только верхний будет сразу же собирать мусор, как обсуждалось по ссылочной ссылке выше.