Jelas, penurunan intuitif dari combinator fixed-point (Y combinator)?

28

Combinator titik tetap FIX (alias combinator Y) dalam kalkulus lambda (tidak diketik) ( ) didefinisikan sebagai:λ

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

Saya mengerti tujuannya dan saya bisa melacak pelaksanaan aplikasinya dengan sangat baik; Saya ingin memahami cara menurunkan FIX dari prinsip pertama .

Di sini sejauh yang saya dapatkan ketika saya mencoba menurunkannya sendiri:

  1. FIX adalah fungsi: FIX λ
  2. FIX mengambil fungsi lain, f , untuk membuatnya rekursif: FIX λf.
  3. Argumen pertama dari fungsi f adalah "nama" dari fungsi, digunakan di mana aplikasi rekursif dimaksudkan. Oleh karena itu, semua tampilan argumen pertama ke f harus diganti dengan fungsi, dan fungsi ini harus mengharapkan sisa argumen f (anggap saja f mengambil satu argumen): FIX λf.f (λy.y)

Di sinilah saya tidak tahu bagaimana "mengambil langkah" dalam penalaran saya. Elips kecil menunjukkan di mana FIX saya kehilangan sesuatu (meskipun saya hanya bisa tahu dengan membandingkannya dengan FIX "nyata").

Saya sudah membaca Jenis dan Bahasa Pemrograman , yang tidak berusaha menurunkannya secara langsung, dan sebagai gantinya merujuk pembaca ke The Little Schemer untuk derivasi. Saya telah membaca itu juga, dan "turunannya" tidak begitu membantu. Selain itu, ini bukan turunan langsung dan lebih banyak menggunakan contoh yang sangat spesifik dan upaya ad-hoc untuk menulis fungsi rekursif yang sesuai di λ .

BlueBomber
sumber
1
Posting ini mungkin membantu. Secara umum, saya pikir hanya melalui dan menghitung beberapa iterasi dari combinator sangat membantu dalam mencari tahu mengapa ia bekerja.
Xodarap
2
Ada beberapa combinator titik tetap yang berbeda. Mungkin orang-orang hanya bermain dengan kombinator sampai mereka menemukan mereka.
Yuval Filmus
@YuvalFilmus, itulah yang penelitian saya dan respon terhadap pertanyaan ini mulai membuat saya berpikir. Tetapi saya masih berpikir itu akan menjadi instruktif untuk "melihat" bagaimana kombinator (s) terbentuk secara logis, suatu keterampilan yang akan sangat membantu ketika, misalnya, mencoba membangun kombinator baru.
BlueBomber
Baca bab 9 dalam "The Little Lisper", oleh Daniel P. Friedman (atau "The Little Schemer").
user18199
2
OP tampaknya mengindikasikan bahwa mereka telah membaca itu.
Raphael

Jawaban:

29

Saya belum membaca ini di mana pun, tapi ini adalah bagaimana saya percaya dapat diturunkan:Y

Mari kita memiliki fungsi rekursif , mungkin faktorial atau yang lainnya. Secara informal, kami mendefinisikan sebagai istilah pseudo-lambda di mana muncul dalam definisi sendiri:fff

f=ff

Pertama, kami menyadari bahwa panggilan rekursif dapat difaktorkan sebagai parameter:

f=(λr.(rr))Mf

Sekarang kita bisa mendefinisikan jika kita hanya punya cara bagaimana menyampaikannya sebagai argumen untuk dirinya sendiri. Ini tidak mungkin, tentu saja, karena kita tidak punya di tangan. Apa yang kita miliki di tangan adalah . Karena berisi semua yang perlu kita definisikan , kita dapat mencoba meneruskan sebagai argumen alih-alih dan mencoba merekonstruksi darinya nanti di dalam. Upaya pertama kami terlihat seperti ini:ffMMfMff

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

Namun, ini tidak sepenuhnya benar. Sebelum, mendapat menggantikan dalam . Tapi sekarang kita melewati sebagai gantinya. Kita harus entah bagaimana memperbaiki semua tempat di mana kita menggunakan sehingga mereka merekonstruksi dari . Sebenarnya, ini tidak sulit sama sekali: Sekarang kita tahu bahwa , di mana-mana kita menggunakan kita cukup menggantinya dengan .frMMrfMf=MMr(rr)

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

Solusi ini bagus, tapi kami harus mengubah di dalamnya. Ini sangat tidak nyaman. Kita dapat melakukan ini dengan lebih elegan tanpa harus memodifikasi dengan memperkenalkan yang mengirim ke argumennya berlaku untuk dirinya sendiri: Dengan menyatakan sebagai kita dapatkanMMλMMλx.M(xx)

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

Dengan cara ini, ketika diganti untuk , diganti untuk , yang menurut definisi sama dengan . Ini memberi kita definisi non-rekursif dari , yang dinyatakan sebagai istilah lambda yang valid!MxMMrff

Transisi ke sekarang mudah. Kita dapat mengambil istilah lambda sewenang-wenang alih-alih dan melakukan prosedur ini. Jadi kita dapat faktor dan mendefinisikanYMM

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

Memang, berkurang menjadi seperti yang kita mendefinisikannya.YMf


Catatan: Saya telah menurunkan seperti yang didefinisikan dalam literatur. Combinator yang telah dijelaskan adalah varian dari untuk panggilan-by-nilai bahasa, kadang-kadang juga disebut . Lihat artikel Wikipedia ini .YYZ

Petr Pudlák
sumber
1
Hilang-tapi-tampaknya-jelas intuisi bahwa tanggapan Anda sangat baik memberi saya adalah bahwa fungsi rekursif perlu dirinya sebagai argumen, jadi kita mulai dengan asumsi bahwa fungsi akan memiliki bentuk untuk beberapa . Kemudian, ketika kita membangun , kita menggunakan pernyataan itu bahwa didefinisikan sebagai aplikasi sesuatu untuk dirinya sendiri secara internal dalam , misalnya, menerapkan ke dalam jawaban Anda, yang menurut definisi sama dengan . Menarik! f=X(X)XXfXxxf
BlueBomber
11

Seperti yang ditunjukkan Yuval, tidak hanya ada satu operator fixed-point. Mereka ada banyak. Dengan kata lain, persamaan untuk teorema titik tetap tidak memiliki jawaban tunggal. Jadi Anda tidak dapat menurunkan operator dari mereka.

Itu seperti bertanya bagaimana orang memperoleh sebagai solusi untuk . Mereka tidak! Persamaannya tidak memiliki solusi unik.(x,y)=(0,0)x=y


Kalau-kalau Anda ingin tahu adalah bagaimana teorema titik tetap pertama ditemukan. Biarkan saya mengatakan bahwa saya juga bertanya-tanya tentang bagaimana mereka datang dengan teorema titik-tetap / rekursi ketika saya pertama kali melihat mereka. Sepertinya sangat cerdik. Terutama dalam bentuk teori komputabilitas. Tidak seperti apa yang dikatakan Yuval, bukan itu masalahnya orang bermain-main sampai mereka menemukan sesuatu. Inilah yang saya temukan:

Sejauh yang saya ingat, teorema ini awalnya karena SC Kleene. Kleene datang dengan teorema titik tetap asli dengan menyelamatkan bukti ketidakkonsistenan kalkulus lambda asli Gereja. Kalkulus lambda asli Gereja menderita paradoks jenis Russel. Kalkulus lambda yang dimodifikasi menghindari masalah. Kleene mempelajari bukti inkonsistensi mungkin untuk melihat bagaimana jika kalkulus lambda yang dimodifikasi akan menderita masalah yang sama dan mengubah bukti inkonsistensi menjadi teorema yang berguna dalam kalkulus lambda yang dimodifikasi. Melalui karyanya tentang kesetaraan kalkulus lambada dengan model komputasi lain (mesin Turing, fungsi rekursif, dll.) Ia memindahkannya ke model komputasi lain.


Bagaimana cara menurunkan operator yang mungkin Anda tanyakan? Inilah cara saya mengingatnya. Teorema titik tetap adalah tentang menghilangkan referensi-diri.

Semua orang tahu paradoks pembohong:

Aku adalah sarang.

Atau dalam bentuk yang lebih linguistik:

Kalimat ini salah.

Sekarang kebanyakan orang berpikir masalah dengan kalimat ini adalah dengan referensi diri. Bukan itu! Referensi-diri dapat dihilangkan (masalahnya adalah dengan kebenaran, sebuah bahasa tidak dapat berbicara tentang kebenaran dari kalimatnya sendiri secara umum, lihat teorema kebenaran Tarski yang tidak dapat ditentukan ). Bentuk rujukan diri dihapus adalah sebagai berikut:

Jika Anda menulis kutipan berikut dua kali, kali kedua di dalam kutipan, kalimat yang dihasilkan salah: "Jika Anda menulis kutipan berikut dua kali, yang kedua di dalam kutipan, kalimat yang dihasilkan salah:"

Tanpa referensi-diri, kami memiliki instruksi tentang cara membuat kalimat dan kemudian melakukan sesuatu dengannya. Dan kalimat yang dibangun sama dengan instruksi. Perhatikan bahwa dalam -calculus kita tidak perlu tanda kutip karena tidak ada perbedaan antara data dan instruksi.λ

Sekarang jika kita menganalisis ini kita memiliki mana adalah instruksi untuk membangun dan melakukan sesuatu untuk itu.MMMxxx

Mx=f(xx)

Jadi adalah dan yang kita milikiMλx.f(xx)

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

Ini untuk diperbaiki . Jika Anda ingin menjadikannya operator, kami hanya menambahkan dan kami mendapatkan :fλfY

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

Jadi aku hanya perlu diingat paradoks tanpa referensi diri dan yang membantu saya memahami apa adalah tentang.Y

Kaveh
sumber
3

Jadi, Anda perlu mendefinisikan kombinator titik tetap

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

tetapi tanpa rekursi eksplisit. Mari kita mulai dengan kombinator irreducible sederhana

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

Di xlambda pertama berulang kali diganti dengan lambda kedua. Konversi alpha sederhana membuat proses ini lebih jelas:

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)

Yakni variabel dalam lambda pertama selalu menghilang. Jadi jika kita menambahkan fke lambda pertama

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

surat fwasiat itu muncul

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

Kami sudah omegamendukung kami . Harus jelas sekarang, bahwa jika kita menambahkan flambda kedua, maka fakan muncul di lambda pertama dan kemudian akan muncul:

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

Sejak

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

kita dapat menulis ulang ekspresi sebagai

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

yang mana saja

f (Y f)

dan kami sudah mendapatkan persamaan kami Y f = f (Y f). Jadi Ykombinator pada dasarnya

  1. gandakan f
  2. buat yang pertama fmuncul
  3. ulangi
pengguna3237465
sumber
2

Anda mungkin telah melihat contoh klasik dari persamaan tanpa bentuk normal:

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

Persamaan serupa disarankan oleh itu untuk rekursi umum:

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

(A) adalah cara untuk menulis persamaan rekursif umum dalam kalkulus lambda (di luar primitif rekursif). Jadi bagaimana Anda menyelesaikan persamaan ? Hubungkan untuk dalam persamaan di atas untuk mendapatkan:Yf=f(Yf)fR

Yf=(λx.f(xx))(λx.f(xx))
Y=λf.(λx.f(xx))(λx.f(xx))
DanielV
sumber