Mewakili Bilangan Negatif dan Kompleks Menggunakan Lambda Calculus

14

Sebagian besar tutorial tentang Lambda Calculus memberikan contoh di mana Integer Positif dan Boolean dapat diwakili oleh Fungsi. Bagaimana dengan -1 dan saya?

zcaudate
sumber

Jawaban:

18

Pertama mengkodekan bilangan dan pasangan alami, seperti yang dijelaskan oleh jmad.

Mewakili integer sebagai pasangan bilangan asli sedemikian rupa sehingga . Kemudian Anda dapat mendefinisikan operasi pada integer sebagai (menggunakan notasi Haskell untuk -calculus):( a , b ) k = a - b λk(a,b)k=abλ

neg = \k -> (snd k, fst k)
add = \k m -> (fst k + fst m, snd k + snd m)
sub = \k m -> add k (neg m)
mul = \k m -> (fst k * fst m + snd k * snd m, fst k * snd m + snd k * fst m)

Kasus bilangan kompleks serupa dalam arti bahwa bilangan kompleks dikodekan sebagai pasangan real. Tetapi pertanyaan yang lebih rumit adalah bagaimana menyandikan real. Di sini Anda harus melakukan lebih banyak pekerjaan:

  1. Encode bilangan rasional sebagai pasangan ( k , a ) di mana k adalah bilangan bulat, a adalah alami, dan q = k / ( 1 + a ) .q(k,a)kaq=k/(1+a)
  2. Mengkodekan bilangan real dengan fungsi f sedemikian rupa sehingga untuk setiap k alam N , f k mengkodekan bilangan rasional q sedemikian rupa sehingga | x - q | < 2 - k . Dengan kata lain, real dikodekan sebagai urutan rasional yang konvergen pada laju k 2 - k .xfkNfkq|xq|<2kk2k

Pengkodean real adalah banyak pekerjaan dan Anda tidak ingin benar-benar melakukannya dalam -kalkulus. Tetapi lihat misalnya subdirektori Marshall untuk implementasi sederhana real di Haskell murni. Ini pada prinsipnya dapat diterjemahkan ke dalam λ -calculus murni .λetc/haskellλ

Andrej Bauer
sumber
1
Wow =) Saya bertanya-tanya secara intuitif apa artinya ... misalnya, menggunakan pengkodean angka gereja ... yaitu. sejumlah gereja nilai integer n diwakili oleh fungsi yang menerapkan fungsi ke nilai n kali. Apakah pasangan dan nilai lambda negatif memiliki perasaan intuitif yang sama tentang mereka?
zcaudate
1
Pengkodean gereja mengkodekan bilangan asli , 1 , 2 , ... Itu tidak mengkodekan angka negatif. Dalam jawaban di atas saya berasumsi Anda sudah tahu tentang pengkodean bilangan alami, jadi saya menjelaskan cara mendapatkan bilangan bulat. Bilangan bulat ketika saya menyandikannya adalah konstruksi yang lebih formal, tidak seperti angka Gereja, yang lebih rumit terhubung dengan λ -kalkulus. Saya tidak berpikir "nilai lambda negatif" adalah ungkapan yang bermakna. 012λ
Andrej Bauer
@zcaudate [Type penjelasan: i:ℤ, x:a, f,u,s:a→a, p:(a→a,a→a)] Jika Anda menyandikan ℤ sebagai (Sign,ℕ)kemudian, diberi sepasang fungsi (s,f)sebagai p, istilah λi.λp.λx.(fst i) (fst p) id ((snd i) (snd p) x)akan menghasilkan baik f(…f(x)…)atau s(f(…f(x)…))(jika hasilnya negatif). Jika Anda menyandikan ℤ as (ℕ,ℕ), Anda memerlukan fungsi yang memiliki invers - diberi pasangan (f,u)dan x, fungsi λi.λp.λx.(snd i)(snd p)((fst i)(fst p) x)akan menghasilkan u(…u(f(…f(x)…))…)yang akan membiarkan waktu yang fditerapkan . Keduanya bekerja dalam konteks yang berbeda (hasilnya dapat "dibalik" | | tidak dapat dibalik). ixf
tidak ada yang
@zcaudate Fungsi-fungsi tambahan diperlukan karena angka yang dikodekan Gereja "muncul kembali sendiri", tetapi pasangan hanya akan memberikan komponennya kepada Anda. Fungsi helper hanya merekatkan komponen bersama-sama dalam urutan "benar" (yang terjadi secara otomatis untuk nats.) Lihat juga: en.wikipedia.org/wiki/… - Pengkodean gereja pada dasarnya fold . ctoruntuk setiap konstruktor dan tipe itu fold( r). (Itulah sebabnya, untuk jenis rekursif, data akan "recurse sendiri" Untuk jenis non-rekursif itu lebih seperti. case/ Pola pertandingan.)
tidak ada yang
13

Lambda-calculus dapat menyandikan sebagian besar struktur data dan tipe dasar. Misalnya, Anda dapat menyandikan sepasang istilah yang ada dalam kalkulus lambda, menggunakan pengkodean Gereja yang sama yang biasanya Anda lihat untuk menyandikan bilangan bulat non-negatif dan boolean:

fst = λ hal . p ( λ x y . x ) snd = λ p . p ( λ x y . y )

pasangan=λxyz.zxy
pertama=λhal.hal(λxy.x)
snd=λhal.hal(λxy.y)

Maka pasangan adalah p = ( pasangan  a b ) dan jika Anda ingin mendapatkan kembali a dan b Anda dapat melakukan ( fst  p ) dan ( snd  p ) .(Sebuah,b)hal=(pasangan Sebuahb)Sebuahb(pertama hal)(snd hal)

Itu berarti bahwa Anda dapat dengan mudah mewakili bilangan bulat positif dan negatif dengan pasangan: tanda di sebelah kiri dan nilai absolut di sebelah kanan. Tanda itu adalah boolean yang menentukan apakah angka itu positif. Hak adalah nomor alami menggunakan pengkodean Gereja.

(sign,n)

xor

mult=λSebuahb.pasangan  (xor(pertama Sebuah)(pertama b))  (mult(snd Sebuah)(snd b))

Untuk mendefinisikan tambahan, Anda harus membandingkan dua bilangan asli dan menggunakan pengurangan ketika tanda-tanda berbeda, jadi ini bukan istilah λ tetapi Anda dapat menyesuaikannya jika Anda benar-benar ingin:

add=λab.{(true,add(snd a)(snd b))if a0b0(false,add(snd a)(snd b))if a<0b<0(true,sub(snd a)(snd b))if a0b<0|a||b|(false,sub(snd b)(snd a))if a0b<0|a|<|b|(true,sub(snd b)(snd a))if a<0b0|a|<|b|(false,sub(snd a)(snd b))if a<0b0|a||b|

tetapi pengurangan itu sangat mudah untuk didefinisikan:

minus=λa.pair(not(fst a))(snd a)
sub=λab.add(a)(minusb)

(a,b)a+bi

add[i]=λz1z2.pair(add(fst z1)(fst z2))(add(snd z1)(snd z2))
jmad
sumber
6
k(a,b)k=ab
Bilangan bulat kompleks baik-baik saja, tetapi ia meminta bilangan kompleks. Kemudian lagi, mereka tentu saja tidak pernah bisa diwakili karena ada yang tak terhitung.
HdM
@AndrejBauer: trik yang sangat bagus (mungkin tidak sesederhana itu) HdM: pasti bisa, bahkan tidak semuanya. Tetapi saya berpikir bahwa metode untuk membangun barang-barang dalam kalkulus λ dengan pengkodean Gereja lebih penting / sesuai di sini.
jmad
Saya berharap saya bisa memberikan dua jawaban yang benar =) Saya bahkan tidak berpikir bahwa real dapat diwakili ketika saya bertanya tentang bilangan kompleks tetapi begitulah!
zcaudate