Odpowiedzi:
Najpierw zakoduj liczby naturalne i pary, jak opisano w jmad.
Reprezentują liczbę całkowitą jako parę liczb naturalnych takich, że . Następnie możesz zdefiniować zwykłe operacje na liczbach całkowitych jako (używając notacji Haskell dla -calculus):( a , b ) k = a - b λ
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)
Przypadek liczb zespolonych jest podobny w tym sensie, że liczba zespolona jest kodowana jako para liczb rzeczywistych. Ale bardziej skomplikowanym pytaniem jest, jak zakodować rzeczywiste. Tutaj musisz wykonać więcej pracy:
Kodowanie reali to dużo pracy i nie chcesz tego robić w -calculus. Ale zobacz na przykład podkatalog Marshall, aby zobaczyć prostą implementację wartości rzeczywistych w czystym Haskell. Można to w zasadzie przetłumaczyć na czysty -calculus.λetc/haskell
i:ℤ
, x:a
, f,u,s:a→a
, p:(a→a,a→a)
] W przypadku kodowania ℤ a (Sign,ℕ)
następnie, ze względu parę funkcji (s,f)
jak p
termin λi.λp.λx.(fst i) (fst p) id ((snd i) (snd p) x)
spowoduje zarówno f(…f(x)…)
lub s(f(…f(x)…))
(jeśli wynik jest ujemny). Jeśli kodujesz ℤ as (ℕ,ℕ)
, potrzebujesz funkcji, która ma odwrotność - biorąc pod uwagę parę (f,u)
i x
, funkcja λi.λp.λx.(snd i)(snd p)((fst i)(fst p) x)
wygeneruje, u(…u(f(…f(x)…))…)
co pozostawi f
zastosowane i
czasy x
. Oba działają w różnych kontekstach (wynik można „odwrócić” || f
jest odwracalny).
fold . ctor
dla każdego konstruktora i tego typu fold
( r
). (Dlatego w przypadku typów rekurencyjnych dane „same się powtarzają”. W przypadku typów nierekurencyjnych bardziej przypomina case
dopasowanie / wzorzec.)
Rachunek Lambda może kodować większość struktur danych i podstawowe typy. Na przykład, możesz zakodować parę istniejących terminów w rachunku lambda, używając tego samego kodowania Kościoła , które zwykle widzisz, aby zakodować nieujemne liczby całkowite i logiczne:
fst = λ p . p ( λ x y . x ) snd = λ p . p ( λ x y . y )
Zatem para to p = ( para a b ), a jeśli chcesz odzyskać a i b , możesz zrobić ( fst p ) i ( snd p ) .
Oznacza to, że możesz łatwo przedstawić dodatnie i ujemne liczby całkowite za pomocą pary: znak po lewej stronie i wartość bezwzględna po prawej stronie. Znak jest wartością logiczną, która określa, czy liczba jest dodatnia. Po prawej jest liczba naturalna z wykorzystaniem kodowania Church.
A teraz, gdy masz względne liczby całkowite. Mnożenie jest łatwe do zdefiniowania, po prostu trzeba zastosować funkcji na znak i mnożenia na liczbach naturalnych w wartości bezwzględnej:
Aby zdefiniować dodanie, musisz porównać dwie liczby naturalne i użyć odejmowania, gdy znaki są różne, więc nie jest to termin λ, ale możesz go dostosować, jeśli naprawdę chcesz:
ale wtedy odejmowanie jest naprawdę łatwe do zdefiniowania:
Gdy masz dodatnie i ujemne liczby całkowite, możesz bardzo łatwo zdefiniować liczby całkowite złożone : jest to tylko para dwóch liczb całkowitych które reprezentują . Zatem dodawanie jest punktowe, a mnożenie jest jak zwykle , ale nie będę tego pisać, powinno być łatwo: