Чітке, інтуїтивне виведення комбінатора з фіксованою точкою (Y комбінатор)?


28

Комбінатор з фіксованою точкою FIX (він же Y-комбінатор) в (нетипізованому) лямбдальному обчисленні ( λ ) визначається як:

λf.(λx.f (λy.x x y)) (λx.f (λy.x x y))

Я розумію його призначення і можу простежити виконання його застосування абсолютно чудово; Я хотів би зрозуміти, як вивести FIX з перших принципів .

Ось, наскільки я отримую, коли намагаюся сам це отримати?

  1. FIX - це функція: FIXλ
  2. FIX бере іншу функцію, f , щоб зробити її рекурсивною: FIX λf.
  3. Перший аргумент функції f - це "ім'я" функції, яка використовується там, де призначена рекурсивна програма. Тому всі види першого аргументу на f повинні бути замінені на функцію, і ця функція повинна очікувати решти аргументів f (припустимо лише, що f бере один аргумент): FIX λf.f (λy.y)

Саме тут я не знаю, як «зробити крок» у своїх міркуваннях. Маленькі еліпси вказують, де мій FIX щось не вистачає (хоча я можу це знати лише порівнявши його з "справжнім" виправленням).

Я вже читав типи та мови програмування , який не намагається отримати це безпосередньо, а натомість скеровує читача до «Маленького схему» для виведення. Я також читав, що і його "виведення" було не таким корисним. Більше того, це менше прямого виведення та більше використання дуже конкретного прикладу та спеціальної спроби написати відповідну рекурсивну функцію в λ .


1
Ця публікація може бути корисною. Взагалі, я думаю, що просто пройти та обчислити кілька ітерацій комбінатора корисно з’ясувати, чому він працює.
Xodarap

2
Існує кілька різних комбінаторів з фіксованою точкою. Можливо, люди просто грали з комбінаторами, поки вони не натрапили на них.
Yuval Filmus

@YuvalFilmus, саме це моє дослідження та відповідь на це запитання починають змушувати мене думати. Але я все-таки думаю, що було б доцільно "бачити", як логічно формуються комбінатори, навички, які були б особливо корисні, наприклад, при спробі побудувати новий комбінатор.
BlueBomber

Прочитайте розділ 9 у «Маленькому лискучі», Даніель П. Фрідман (або «Маленький шемер»).
користувач18199

2
Здається, ОП вказує на те, що вони вже це прочитали.
Рафаель

Відповіді:


29

Я ніде цього не читав, але я вважаю, що міг би отримати це:Y

Будемо мати рекурсивну функцію , можливо, факториальну чи щось подібне. Неофіційно ми визначаємо f як псевдо лямбда-термін, де f зустрічається в його власному визначенні:fff

f=ff

По-перше, ми розуміємо, що рекурсивний виклик може бути врахований як параметр:

f=(λr.(rr))Мf

Тепер ми могли б визначити якби мав лише спосіб, як передати це як аргумент собі. Це не можливо, звичайно, тому що ми не маємо п під рукою. Те , що ми маємо під рукою M . Оскільки M містить усе, що потрібно для визначення f , ми можемо спробувати передати M як аргумент замість f і спробувати реконструювати f з нього пізніше всередині. Наша перша спроба виглядає так:ffММfМff

f=(λr.(rr))M(λr.(rr))M

Однак це не зовсім правильно. Перед тим , отримали замінити г всередині М . Але тепер ми передаємо М замість цього. Ми повинні як - то виправити всі місця , де ми використовуємо г , щоб вони реконструкції п від М . Власне, це зовсім не складно: Тепер, коли ми знаємо, що f = M M , скрізь, де ми використовуємо r, ми просто замінюємо його на ( r r ) .frMMrfMf=MMr(rr)

f=(λr.((rr)(rr)))M(λr.((rr)(rr)))M

Це рішення добре, але нам довелося змінити всередині. Це не дуже зручно. Ми можемо зробити це більш елегантно, не змінюючи M , ввівши інший λ, який надсилає M свій аргумент, застосований до самого себе: Висловивши M ' як λ x . M ( x x ) отримуємоMMλMMλx.M(xx)

f=(λx.(λr.(rr))M(xx))(λx.(λr.(rr))M(xx))

Таким чином, коли заміщений на x , M M заміщений на r , що за визначенням дорівнює f . Це дає нам нерекурсивне визначення f , виражене як дійсний лямбда-термін!MxMMrff

Перехід до тепер легкий. Ми можемо взяти довільний лямбда-термін замість M і виконати на ньому цю процедуру. Таким чином, ми можемо виділити M і визначитиYMM

Y=λm.(λx.m(xx))(λx.m(xx))

Дійсно, зводиться до f, як ми його визначили.YMf


Примітка. Я вивів як це визначено в літературі. Комбінатор ви описали це варіант Y для виклику за значенням мов, іноді також називають Z . Дивіться цю статтю у Вікіпедії .YYZ


1
Відсутній но-здавалося б, очевидно , інтуїція , що ваш відмінний відповідь дав мені, що рекурсивна функція повинна себе в якості аргументу, тому ми почнемо з припущення , що функція буде мати вигляд для деякого X . Тоді, будуючи X , ми використовуємо те твердження, що f визначається як застосування чогось до себе внутрішньо в X , наприклад, застосовуючи х у х у своїй відповіді, що за визначенням дорівнює f . Захоплююче! f=X(X)XXfXxxf
BlueBomber

11

Як зазначив Юваль, існує не один оператор з фіксованою точкою. Їх багато. Іншими словами, рівняння для теореми з фіксованою точкою не мають однозначної відповіді. Таким чином, ви не можете отримати від них оператора.

Це як запитати, як люди виводять як рішення для x = y . Вони ні! Рівняння не має унікального рішення.(x,y)=(0,0)x=y


На всякий випадок, що ви хочете знати, як було виявлено першу теорему з фіксованою точкою. Дозвольте сказати, що я також цікавився тим, як вони придумали теореми з фіксованою точкою / рекурсією, коли я вперше їх побачив. Це здається геніальним. Особливо у формі теорії обчислюваності. На відміну від того, що Юваль каже, це не так, що люди грали, поки щось не знайшли. Ось що я знайшов:

Наскільки я пам’ятаю, теорема спочатку обумовлена ​​SC Kleene. Клійн придумав оригінальну теорему з фіксованою точкою, виправдавши доказ невідповідності початкового обчислення лямбда Церкви. Первісне лямбда-числення церкви зазнало парадоксу типу Русселя. Модифікований лямбдальний чисел уникнув проблеми. Клійн, мабуть, вивчив доказ невідповідності, щоб зрозуміти, як, якщо модифікована численність лямбда постраждає від подібної проблеми, і перетворив доказ невідповідності в корисну теорему модифікованого обчислення лямбда. Своєю роботою щодо еквівалентності обчислення ламбади з іншими моделями обчислень (машини Тюрінга, рекурсивні функції тощо) він переніс її на інші моделі обчислення.


Як отримати оператора, який ви можете запитати? Ось як я це пам’ятаю. Теорема з фіксованою точкою стосується зняття самовідсилання.

Всім відомий парадокс брехуна:

Я - лігво.

Або в більш мовній формі:

Це речення хибне.

Зараз більшість людей вважає, що проблема з цим реченням полягає в самонаведенні. Це не так! Самопосилання може бути усунено (проблема з правдою, мова взагалі не може говорити про істинність власних речень; див. Теорему про невизначеність істини Тарського ). Форма, у якій знімається самонавіювання, така:

Якщо ви пишете наступну цитату двічі, другий раз всередині лапок, отримане речення є помилковим: "Якщо ви пишете наступну цитату двічі, другий раз всередині лапок, отримане речення є помилковим:"

Ніякої самонавіювання, у нас є інструкції про те, як побудувати речення, а потім зробити щось із ним. А речення, яке вибудовується, дорівнює вказівкам. Зауважте, що у -калькуляції нам не потрібні лапки, оскільки немає різниці між даними та інструкціями.λ

Тепер, якщо ми проаналізуємо це, у нас є де M x - це інструкція побудувати x x і зробити щось для цього.MMMxxx

Mx=f(xx)

Отже дорівнює λ x . f ( x x ) і маємоMλx.f(xx)

MM=(λx.f(xx))(λx.f(xx))

This is for a fixed f. If you want to make it an operator we just add λf and we get Y:

Y=λf.(MM)=λf.((λx.f(xx))(λx.f(xx)))

So I just keep in mind the paradox without self-reference and that helps me understand what Y is about.


3

So you need to define a fixed point combinator

fix f = f (fix f)
      = f (f (fix f))
      = f (f (f ... ))

but without explicit recursion. Let's start with the simplest irreducible combinator

omega = (\x. x x) (\x. x x)
      = (\x. x x) (\x. x x)
      = ...

The x in the first lambda is repeatedly substituted by the second lambda. Simple alpha-conversion makes this process clearer:

omega =  (\x. x x) (\x. x x)
      =α (\x. x x) (\y. y y)
      =β (\y. y y) (\y. y y)
      =α (\y. y y) (\z. z z)
      =β (\z. z z) (\z. z z)

I.e. the variable in the first lambda always disappears. So if we add an f to the first lambda

(\x. f (x x)) (\y. y y)

the f will bob up

f ((\y. y y) (\y. y y))

We have got our omega back. It should be clear now, that if we add an f to the second lambda, then the f will appear in the first lambda and then it will bob up:

Y f = (\x. x x)     (\x. f (x x))
      (\x. f (x x)) (\x. f (x x)) -- the classical definition of Y

Since

(\x. s t) z = s ((\x. t) z), if `x' doesn't occur free in `s'

we can rewrite the expression as

f ((\x. x x) (\x. f (x x))

which is just

f (Y f)

and we have got our equation Y f = f (Y f). So the Y combinator is essentially

  1. double the f
  2. make the first f bobbed up
  3. repeat

2

You may have seen the classic example of an equation without a normal form:

(λx.xx)(λx.xx)(λx.xx)(λx.xx)

A similar equation is suggested by that for general recursion:

(A)(λx.R(xx))(λx.R(xx)) R( (λx.R(xx))(λx.R(xx)) )R(R( (λx.R(xx))(λx.R(xx)) ))

(A) is a way to write general recursive equations in lambda calculus (beyond primitive recursive). So how you solve the equation Yf=f(Yf) ? Plug f in for R in the above equation to get:

Yf=(λx.f(xx))(λx.f(xx))
Y=λf.(λx.f(xx))(λx.f(xx))
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.