Представлення негативних та складних чисел за допомогою обчислення лямбда


14

Більшість навчальних посібників з обчислення лямбда надають приклад, коли позитивні цілі чи булеві символи можуть бути представлені функціями. Що про -1 і я?

Відповіді:


18

Спочатку кодуйте натуральні числа та пари, як описано jmad.

Представіть ціле число к як пару натуральних чисел (а,б) таких, що к=а-б . Тоді ви можете визначити звичайні операції над цілими числами (використовуючи позначення Haskell для λ -cculus):

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)

Випадок складних чисел схожий у тому сенсі, що складне число кодується як пара дій. Але складнішим питанням є кодування реалів. Тут вам доведеться зробити більше роботи:

  1. Кодуйте раціональне число як пару ( k , a ), де k - ціле число, a - природне, а q = k / ( 1 + a )q(к,а)каq=к/(1+а) .
  2. Кодуйте дійсне число функцією f такою, що для кожного природного k N , f k кодує раціональне число q таке, що | х - q | < 2 - k . Іншими словами, реальне кодується як послідовність раціоналів, що сходяться до нього зі швидкістю k 2 - k .хfкNfкq|х-q|<2-кк2-к

Кодування реалів - це велика робота, і ви не хочете насправді робити це у -калькуляції. Але дивіться, наприклад, підкаталог Маршалла для простої реалізації дій у чистому Haskell. Це, в принципі, можна перекласти на чистий λ -рахунок.λetc/haskellλ


1
Вау =) Інтуїтивно мені цікаво, що це означає ... наприклад, використовуючи кодування церковних чисел ... тобто. церковне число цілого значення n представлено функцією, яка застосовує функцію до значення n разів. Чи мають пари та негативні значення лямбда таке інтуїтивне відчуття щодо них?
zcaudate

1
Церковне кодування кодує натуральні числа , 1 , 2 , ... Це не кодує негативні числа. У відповіді вище я припускав, що ви вже знаєте про кодування натуральних чисел, тому я пояснив, як отримати цілі числа. Цілі числа, котрі я кодував їх, є більш формальною конструкцією, на відміну від церковних цифр, які більш складно пов'язані з λ- обчисленням. Я не думаю, що "негативні лямбда-значення" - це змістовна фраза. 012λ
Андрій Бауер

@zcaudate [Тип анотація: i:ℤ, x:a, f,u,s:a→a, p:(a→a,a→a)] Якщо ви закодувати ℤ , як (Sign,ℕ)то, враховуючи пар функцій , (s,f)як pцей термін λi.λp.λx.(fst i) (fst p) id ((snd i) (snd p) x)буде виробляти або f(…f(x)…)або s(f(…f(x)…))(якщо результат негативний). Якщо ви кодуєте ℤ як (ℕ,ℕ), вам потрібна функція, яка має зворотну задану пару, (f,u)і xфункція λi.λp.λx.(snd i)(snd p)((fst i)(fst p) x)буде виробляти, u(…u(f(…f(x)…))…)яка залишить fзастосований iчас до x. Обидва працюють в різних контекстах (результат можна "перевернути" || fнеперевернутий).
ніхто

@zcaudate Додаткові функції необхідні, оскільки закодовані Церквою числа "повторюються самостійно", але пари передають вам лише їх компоненти. Допоміжні функції просто склеюють компоненти разом у "правильному" порядку (що відбувається автоматично для нац.) Дивіться також: en.wikipedia.org/wiki/… - Кодування церкви в основному fold . ctorдля будь-якого конструктора і цього типу fold( r). (Саме тому, для рекурсивних типів, дані будуть «рекурсія на своєму» Для НЕ рекурсивних типів це більше схожі. case/ Матч шаблону.)
ніхто НЕ

13

Лямбда-числення може кодувати більшість структур даних та основних типів. Наприклад, ви можете кодувати пару існуючих термінів в обчисленні лямбда, використовуючи те саме кодування Церкви, яке зазвичай бачите для кодування негативних цілих чисел та булевих:

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

pair=λxyz.zxy
fst=λp.p(λxy.x)
snd=λp.p(λxy.y)

Тоді пара - p = ( пара  a b ), і якщо ви хочете повернутися a і b, ви можете зробити ( fst  p ) і ( snd  p )(a,b)p=(pair ab)аб(fst p)(snd p) .

Це означає, що ви можете легко представити додатні та від’ємні цілі числа за допомогою пари: знак зліва та абсолютне значення праворуч. Знак - булева, яка визначає, чи є позитивним число. Право - це натуральне число з використанням кодування Церкви.

(sign,n)

А тепер у вас відносні цілі числа. Множення легко визначити, потрібно просто застосувати функціюxor від знака і множення на натуральних числах по абсолютній величині:

mult=λab.pair  (xor(fst a)(fst b))  (mult(snd a)(snd b))

Щоб визначити додавання, вам слід порівняти два натуральних числа та використати віднімання, коли знаки різні, тому це не λ-термін, але ви можете адаптувати його, якщо дійсно хочете:

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|

але тоді відняття визначити дуже просто:

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))

6
You can avoid the case distinctions if instead you represent the integer k as a pair of natural numbers (a,b) such that k=ab.
Andrej Bauer

Complex integers alright, but he was asking for complex numbers. Then again, they of course can never be represented since there are uncountable.
HdM

@AndrejBauer: very nice trick (maybe not that simpler) HdM: sure they can, even in not all of them. But I figured that the method for building stuff in the λ-calculus with Church encoding was more important/appropriate here.
jmad

I wish I could give two correct answers =) I wasn't even thinking that reals could be represented when I asked about complex numbers but there you go!.
zcaudate
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.