Większość samouczków na temat rachunku Lambda stanowi przykład, w którym dodatnie liczby całkowite i liczby boolowskie mogą być reprezentowane przez funkcje. Co z -1 i ja?
Większość samouczków na temat rachunku Lambda stanowi przykład, w którym dodatnie liczby całkowite i liczby boolowskie mogą być reprezentowane przez funkcje. Co z -1 i ja?
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)
jakp
terminλi.λp.λx.(fst i) (fst p) id ((snd i) (snd p) x)
spowoduje zarównof(…f(x)…)
lubs(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)
ix
, funkcjaλi.λp.λx.(snd i)(snd p)((fst i)(fst p) x)
wygeneruje,u(…u(f(…f(x)…))…)
co pozostawif
zastosowanei
czasyx
. Oba działają w różnych kontekstach (wynik można „odwrócić” ||f
jest odwracalny).fold . ctor
dla każdego konstruktora i tego typufold
(r
). (Dlatego w przypadku typów rekurencyjnych dane „same się powtarzają”. W przypadku typów nierekurencyjnych bardziej przypominacase
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 ) .( a , b ) p = ( para a b ) za b ( fst p ) ( 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ć funkcjixor 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:(a,b) a+bi
źródło