Definiując COMBINATOR, który:
jest zdefiniowany jako termin lambda bez zmiennych wolnych, więc z definicji każdy syntezatora jest już termin lambda,
można określić, na Przykładowo, struktura lista, pisząc:
Y = (list definition in lambda calculus)
Y LIST = (list definition in lambda calculus) LIST
Y LIST = (element insertion definition in lambda calculus)
intuicyjnie i stosując operator paradoksalny, możliwa jest definicja - rozważyć \ = lambda:
- lista jest pusta, a następnie element końcowy, na przykład
0
;
- lub lista jest utworzona przez element
x
, który może być inną listą w obrębie poprzedniej.
Ponieważ został zdefiniowany przez kombinator - kombinator punktowy stały - nie ma potrzeby wykonywania dalszych aplikacji, poniższa abstrakcja jest terminem lambda.
Y = \f.\y.\x.f (x y)
Teraz nazywania jej listy:
Y LIST = (*\f*.\y.\x.*f* (x y)) *LIST* -- applying function name
LIST = \y.\x.LIST (x y), and adding the trailing element "0"
LIST = (\y.\x.LIST (x y)) 0
LIST = (*\y*.\x.LIST (x *y*)) *0*
LIST = \x.LIST (x 0), which defines the element insertion abstraction.
operator paradoksalny Y
, lub po prostu COMBINATOR, pozwala rozważyć definicję LISTA już ważny element, bez zmiennych wolnych, tak , bez potrzeby redukcji.
Następnie można dołączyć/wstawić elementy, powiedzmy 1 i 2, wykonując:
LIST = (\x.LIST (x 0)) 1 2 =
= (*\x*.LIST (*x* 0)) *1* 2 =
= (LIST (1 0)) 2 =
Ale tutaj, wiemy definicji listy, więc go rozwinąć:
= (LIST (1 0)) 2 =
= ((\y.\x.LIST (x y)) (1 0)) 2 =
= ((*\y*.\x.LIST (x *y*)) *(1 0)*) 2 =
= (\x.LIST (x (1 0))) 2 =
teraz, wstawianie elemenet 2
:
= (\x.LIST (x (1 0))) 2 =
= (*\x*.LIST (*x* (1 0))) *2* =
= LIST (2 (1 0))
który może zarówno zostać rozszerzona, w przypadku nowego wkładania, o r po prostu pozostaje tak, jak jest, ze względu na to, że LISTA jest terminem lambda, zdefiniowanym przez kombinator.
Rozszerzenie dla przyszłych wstawkami:
= LIST (2 (1 0)) =
= (\y.\x.LIST (x y)) (2 (1 0)) =
= (*\y*.\x.LIST (x *y*)) *(2 (1 0))* =
= \x.LIST (x (2 (1 0))) =
= (\x.LIST (x (2 (1 0)))) (new elements...)
Cieszę się, że udało mi się wyprowadzić ten sam, ale jestem pewien, że musi być jakiś dobry grono dodatkowych warunków, przy definiowaniu stos, kupa lub jakaś bardziej wyszukana struktura.
Próbuje wyprowadzić abstrakcji dla wstawiania/usuwania stos - bez wszystko krok po kroku:
Y = \f.\y.\x.f (x y)
Y STACK 0 = \x.STACK (x 0)
STACK = \x.STACK (x 0)
Aby wykonać operację na nią, nazwijmy pustego stosu - przypisanie zmiennej (:
stack = \x.STACK (x 0)
// Insertion -- PUSH STACK VALUE -> STACK
PUSH = \s.\v.(s v)
stack = PUSH stack 1 =
= (\s.\v.(s v)) stack 1 =
= (\v.(stack v)) 1 =
= (stack 1) = we already know the steps from here, which will give us:
= \x.STACK (x (1 0))
stack = PUSH stack 2 =
= (\s.\v.(s v)) stack 2 =
= (stack 2) =
= \x.STACK x (2 (1 0))
stack = PUSH stack 3 =
= (\s.\v.(s v)) stack 3 =
= (stack 3) =
= \x.STACK x (3 (2 (1 0)))
a my po raz kolejny imię ten wynik, dla nas do pop elementy:
stack = \x.STACK x (3 (2 (1 0)))
// Removal -- POP STACK -> STACK
POP = \s.(\y.s (y (\t.\b.b)))
stack = POP stack =
= (\s.(\y.s y (\t.\b.b))) stack =
= \y.(stack (y (\t.\b.b))) = but we know the exact expansion of "stack", so:
= \y.((\x.STACK x (3 (2 (1 0)))) (y (\t.\b.b))) =
= \y.STACK y (\t.\b.b) (3 (2 (1 0))) = no problem if we rename y to x (:
= \x.STACK x (\t.\b.b) (3 (2 (1 0))) =
= \x.STACK x (\t.\b.b) (3 (2 (1 0))) = someone guide me here, if i'm wrong
= \x.STACK x (\b.b) (2 (1 0)) =
= \x.STACK x (2) (1 0) =
= \x.STACK x (2 (1 0))
Na co, mamy nadzieję, mamy element 3
.
Próbowałem sam to wyprowadzić, więc jeśli istnieją jakiekolwiek ograniczenia z rachunku lambda, których nie śledziłem, proszę, wskazuj to.
Czy pojedynczo nie łączono idealnego stosu z 'push' =' cons' i 'pop' =' head/tail'? Podnoszę to, ponieważ pojedynczo połączone listy zostały zrobione tysiąc razy i mogą być łatwiejsze do przemyślenia. – delnan
@delnan Jest to bliskie podejściu zaproponowanemu w mojej odpowiedzi, ponieważ użyłem części definicji 'list' do zdefiniowania' stosu'. – Rubens