Lambda račun
U matematičkoj logici i računarstvu, lambda račun, odnosno
Lambda račun se slobodno može nazvati najmanjim univerzalnim programskim jezikom. Sastoji se od jednog transformacijskog pravila (supstitucija varijable) i jednog načina definicije funkcije. Lambda račun je univerzalan na način da bilo koja izračunljiva funkcija može biti izražena i evaluirana koristeći njegov formalizam. Ovo je stoga istovjetno formalizmu Turingovog stroja. Međutim, lambda račun naglašava transformacijska pravila i ne zamara se stvarnim strojem koji ih ostvaruje. U tom duhu, predstavlja pristup srodniji programskoj podršci nego sklopovlju.
Ovaj se članak bavi "netipiziranim lambda računom", kako ga je izvorno osmislio Church. U međuvremenu su se razvili tipizirani lambda računi.
Izvorno, Church je pokušao konstruirati potpun formalni sustav kao osnovu matematike - kad se ispostavila podložnost sustava analogonu Russellovog paradoksa, odvojio je lambda račun i koristio ga za proučavanje izračunljivosti, što je pak kulminiralo u davanju negativnog odgovora na Entscheidungsproblem.
U lambda računu, svaki izraz stoji za funkciju jednog argumenta (argument - ulaz funkcije) - argument je funkcije također funkcija jednog argumenta, a vrijednost je funkcije druga funkcija jednog argumenta. Funkcija je anonimno definirana lambda izrazom koji izražuje djelovanje funkcije na njene argumente. Primjerice, "dodaj-dva" funkcija f takva da f(x) = x + 2
bi mogla u lambda računu biti izražena kao
(ili ekvivalentno kao
; ime formalnog argumenta ne igra ulogu) a broj f(3)
bi bio zapisan kao (
. Aplikacija funkcije je asocijativna ulijevo: f x y = (f x) y
. Neka se razmotri funkcija koja prima funkciju kao argument i aplicira je se na broj 3
:
. Ova bi potonja funkcija mogla biti aplicirana na prethodnu "dodaj-dva" funkciju na sljedeći način: (
. Ova tri izraza : (
i (
i 3 + 2
su ekvivalentni. Funkcija dvaju varijabli je u lambda računu izražena kao funkcija jednog argumenta koja vraća funkciju jednog argumenta (vidi currying). Primjerice, funkcija f(x, y) = x - y
bi bila zapisana kao
. Uobičajena je konvencija skratiti curried funkcije kao, na primjer,
.
Ne može svaki lambda izraz biti reduciran na konačnu vrijednost poput onih gore. Na primjer
(
λ x. x x) (λ x. x x)
ili
(
λ x. x x x) (λ x. x x x)
i pokušajmo vizualizirati što se dogodi kad se aplicira prva funkcija na svoj argument.
(
je također poznat kao ((
je poznat kao ((
kao
Iako sam lambda račun ne sadrži simbole za cijele brojeve ili zbrajanje, ovi mogu biti definirani kao kratice unutar računa i aritmetika može biti izražena kao što će dolje biti pokazano.
Izrazi lambda računa mogu sadržavati slobodne varijable, tj. varijable koje ne veže nijedna
. Na primjer, varijabla y
je slobodna u izrazu (
, koji predstavlja funkciju koja uvijek daje rezultat y
. Povremeno, ovo stvara potrebu za preimenovanjem formalnih argumenata, na primjer kako bi se reducirao
(
λ x y. y x) (λ x. y) naλ z. z (λ x. y)
Ako se pojam aplikacije funkcije formalizira pri čemu se ne dozvole lambda izrazi, dobije se kombinatorna logika.
Formalno, započinje se s prebrojivo beskonačnim skupom identifikatora, npr. {a, b, c, ..., x, y, z, x1, x2, ...}
. Skup svih lambda izraza može biti opisan sljedećom kontekstno neovisnom gramatikom u BNF:
<izraz> ::= <identifikator>
<izraz> ::= (
λ <identifikator>. <izraz>)<izraz> ::= (<izraz> <izraz>)
Prva dva pravila generiraju funkcije, dok treće opisuje aplikaciju funkcije na argument. Obično su zagrade za lambda apstrakciju (pravilo 2) i aplikaciju funkcije (pravilo 3) izostavljene ako ne postoji nejednoznačnost pod pretpostavkom da je (1) lambda aplikacija asocijativna ulijevo i (2) lambda veže cijeli izraz koji slijedi. Na primjer, izraz ((
se može jednostavno napisati kao (
.
Lambda izrazi kao što je
ne definiraju funkcije jer je pojavljivanje varijable y
slobodno, tj. nije vezano nijednom
u izrazu. Vezanje pojavljivanja varijabli je (matematičkom indukcijom nad strukturom lambda izraza) definirano sljedećim pravilima:
- U izrazu oblika
V
, gdje jeV
varijabla, ovoV
je jedino slobodno pojavljivanje. - U izrazu oblika
λ V. EE
osim onih odV
. U ovom se slučaju za pojavljivanjaV
uE
kaže da su vezana sa
prijeλ V
. - U izrazu oblika
(E E′)
, slobodna pojavljivanja su slobodna pojavljivanja uE
iE′
.
Nad skupom lambda izraza je definirana relacija ekvivalencije (ovdje označena kao ==
) koja obuhvaća intuitivan koncept da izrazi označuju istu funkciju. Ova relacija ekvivalencije je definirana pravilom
Pravilo alfa-konverzije je namijenjeno izražavanju ideje da su imena vezanih varijabli nevažna - a primjer da su
i
iste funkcije. Međutim, pravilo nije jednostavno kao što se na prvi pogled čini (vidi lambda uzdizanje) za praktičnu implementaciju). Postoji nekoliko ograničenja na to kad vezana varijabla može biti zamijenjena drugom. Primjerice, ako se zamijeni x s y u
Pravilo alfa-konverzije iskazuje da ako su V
i W
varijable, E
je lambda izraz i
E[V := W]
znači izraz E
sa svakim slobodnim pojavljivanjem V
u E
zamijenjenim sa W
, i tada
λ V. E ==λ W. E[V := W]
ako se W
ne pojavljuje slobodno untar E
i W
nije vezan sa
unutar E
kadgod zamjenjuje V
. Ovo pravilo na primjer govori da
je isto kao i
.
Kao primjer uočavamo da je
for (int i = 0; i < max; i++) { proc(i); }
istovjetno
for (int j = 0; j < max; j++) { proc(j); }
Pravilo beta-redukcije izražava ideju aplikacije funkcije.
Kaže da vrijedi
((
λ V. E) E′) == E[V := E′]
ako sva slobodna pojavljivanja u E′
ostaju slobodna u E[V := E′]
.
Relacija ==
je tad definirana kao najmanja relacija ekvivalencije koja zadovoljava ova dva pravila.
Više operacijska definicija relacija ekvivalencije može biti dana apliciranjem pravila samo slijeva na desno. Izraz oblika ((
se zove beta redeks. Lambda izraz koji ne dopušta nijednu beta redukciju, tj. nema beta redeksa kao podizraza, se zove normalni oblik. Nije svaki lambda izraz ekvivalentan normalnom obliku, ali ako jest, taj je normalan oblik jedinstven do na imenovanje vezanih varijabli. Nadalje, postoji algoritam za računanje normalnih oblika: zamjenjuj prvu (krajnje lijevu) varijablu odgovarajućim stvarnim argumentom, sve dok daljnja redukcija nije moguća. Ovaj algoritam zaustavlja ako i samo ako lambda izraz posjeduje normalni oblik. Church-Rosserov teorem tada kaže da dva izraza rezultiraju u istom normalnom obliku do na preimenovanje vezanih varijabli ako i samo ako su ekvivalnetni.
Postoji i treće pravilo, eta-konverzija, koje može biti dodano ovim dvama kako bi se oformila nova relacija ekvivalencije. Eta-konverzija izražuje ideju ekstenzionalnosti (opsegovnosti), koja je u ovom konstekstu ta da su dvije funkcije jednake ako i samo ako daju isti rezultat za sve argumente. Eta-konverzija pretvara između
i f
kadgod se x
ne pojavljuje slobodno u f
. Ovo se može shvatiti kao istovjetno ekstenzionalnosti kako slijedi:
Ako su f
i g
ekstenzionalno ekvivalentne, tj. ako f a==g a
za sve lambda izraze a
, tada posebice uzimanjem a
kao varijable a
koja se ne pojavljuje slobodna u f
i g
imamo
f x == g x
te stoga
, te stoga eta-konverzijom slijedi f == g
. Stoga ako uzmemo eta-konverziju kao validnu, iznalazimo da je ekstenzionalnost također validna.
Vrijedi i obratno, ako je ekstenzionalnost uzeta kao validna, tada s obzirom na to da beta redukcijom slijedi da za sve y
imamo
(
, imamo
; tj. eta-converzija je validna.
Nekoliko je mogućih načina za definirati prirodne brojeve u lambda računu, ali daleko najuobičajeniji su Churchovi numerali, koji mogu biti definirani na sljedeći način:
0 :=
λ f x. x1 :=
λ f x. f x2 :=
λ f x. f (f x)3 :=
λ f x. f (f (f x))
i tako dalje. Intuitivno, broj n
u lambda računu je funkcija koja prima funkciju f
kao argument i vraća n
-tu kompoziciju od f
. Drugim riječima, Churchov je numeral funkcija višeg reda - prihvaća jednoargumentnu funkciju f
i vraća drugu jednoargumentnu funkciju.
(Valja uočiti da se u izvornom Churchovom lambda računu zahtijevalo bar jedno pojavljivanje formalnog parametra lambda izraza u tijelu funkcije, što gornju definiciju broja 0 čini nemogućom.)
Za ovu definiciju Churchovih numerala, može se definirati funkcija sljedbenika, koja uzima broj n
i vraća n + 1
:
SLJED :=
λ n f x. f ((n f) x)
Zbrajanje je definirano na sljedeći način:
PLUS :=
λ m n f x. n f (m f x)
PLUS
se može shvatiti kao funkcija koja uzima dva prirodna broja kao argumente i vraća prirodni broj. Zabavno je provjeriti da su
PLUS 2 3
i5
ekvivalentni lambda izrazi. Množenje može biti definirano kao:
MNOŽ :=
,λ m n. m (PLUS n) 0
ideja množenja m i n je ista kao i m puta dodavanja n nuli. Alternativno,
MNOŽ :=
λ m n f. m (n f)
Prethodnik PRED n = n - 1
pozitivnog cijelog broja n je nešto teži:
PRED :=
λ n f x. n (λ g h. h (g f)) (λ u. x) (λ u. u)
i alternativno:
PRED :=
λ n. n (λ g k. (g 1) (λ u. PLUS (g k) 1) k) (λ v. 0) 0
Valja uočiti trik (g 1) (
koji evaluira u k
ako je g(1)
nula i u g(k) + 1
inače.
Po konvenciji, sljedeće su dvije definicije (poznate kao Churchovi booleani) korištene za bulovske vrijednosti ISTINA
i LAŽ
:
ISTINA :=
λ x y. xLAŽ :=
λ x y. y- (Uočimo da je
LAŽ
ekvivalentan Churchovom numeralu nula definiranog gore)
- (Uočimo da je
Tada, s ovim dvama
I :=
λ p q. p q LAŽILI :=
λ p q. p ISTINA qNE :=
λ p. p LAŽ ISTINAAKOTADAINAČE :=
λ p x y. p x y
Sada se mogu izračunati neke logičke funkcije, poput na primjer:
I ISTINA LAŽ
≡ (
λ p q. p q LAŽ) ISTINA LAŽ →β ISTINA LAŽ LAŽ≡ (
λ x y. x) LAŽ LAŽ →β FALSE
sad se lako vidi je da je I ISTINA LAŽ
ekvivalentan LAŽ
.
Predikat je funkcija koja vraća bulovsku vrijednost. Najfundamentalniji predikat je JELINULA
koji vraća ISTINA
ako je njegov argument Churchov numeral 0
, i LAŽ
ako je njegov argument neki drugi Churchov numeral:
JELINULA :=
λ n. n (λ x. LAŽ) ISTINA
Dostupnost predikate i gornje definicije vrijednosti ISTINA
i LAŽ
čine zgodnim napisati "ako-tada-inače" naredbe u lambda računu.
Par (dvojka) kao tip podataka može biti definiran u terminima vrijednosti ISTINA
i LAŽ
.
CONS :=
λ f.λ s.λ b. b f sCAR :=
λ p. p ISTINACDR :=
λ p. p LAŽNIL :=
λ x.ISTINANULL :=
λ p. p (λ x y.LAŽ)
Vezana lista kao tip podataka može biti definirana ili kao NIL za praznu listu, ili kao CONS
elementa i manje liste.
Rekurzija je definicija funkcije rabeći samu funkciju. Naizgled, lambda račun ovo ne dopušta. Međutim, ovaj je utisak pogrešan. Razmotrimo na primjer funkciju faktorijela f(n)
rekurzivno definiranu kao
f(n) = 1, ako n = 0; i n·f(n-1), ako n>0
.
U lambda se računu ne može definirati funkcija koja uključuje samu sebe. Kako bi se ovo zaobišlo, može se započeti definiranjem funkcije, ovdje zvanom g
, koja prima funkciju f
kao argument i vraća drugu funkciju koja prima n
kao argument:
g :=
.λ f n. (1, ako n = 0; i n·f(n-1), ako n>0)
Funkcija koju g
vraća je ili konstanta 1
ili n puta aplikacija funkcije f
nad n-1
. Rabeći predikat JELINULA
, bilo koje bulovske i algebarske definicije gore opisane, funkcija g
može biti definirana u lambda računu.
Međutim, sama g
još uvijek nije rekurzivna. - kako bismo koristili g
za stvaranje rekurzivne funkcije faktorijela, funkcija prosljeđena g
kao f
mora imati specifična svojstva. Ponajprije, funkcija prosljeđena kao f
se mora ekspandirati u funkciju g
pozvanu s jednim argumentom - i taj argument mora biti funkcija koja je opet proslijeđena f
!
Drugim riječima, f
mora ekspandirati u g(f)
. Ovaj poziv g
će se tad ekspandirati u gornju funkciju faktorijela i izračunati u još jednu razinu rekurzije. U toj će se ekspanziji funkcija f
opet pojaviti i opet će se ekspandirati u g(f)
i nastaviti rekurziju. Ova se vrsta funkcije, kad vrijedi da je f = g(f)
, zove fiksna točka od g
, i ispada da može biti implementirana u lambda računu onim što je poznato kao paradoksalni kombinator ili operator fiksne točke i predstavljen je kao Y
- Y kombinator:
Y =
λ g. (λ x. g (x x)) (λ x. g (x x))
U lambda računu, Y g
je fiksna točka od g
, s obzirom na to da ekspandira u g (Y g)
. Sada, da bismo kompletirali naš rekurzivni poziv funkcije faktorijela, jednostavno pozivamo g (Y g) n
, pri čemu je n broj puta koliko izračunavamo faktorijelu.
Za dan n = 5, na primjer, ovo ekspandira u:
(
λ n.(1, ako n = 0; i n·((Y g)(n-1)), ako n>0)) 51, ako 5 = 0; i 5·(g(Y g)(5-1)), ako 5>0
5·(g(Y g) 4)
5·(
λ n. (1, ako n = 0; i n·((Y g)(n-1)), ako n>0) 4)5·(1, ako 4 = 0; i 4·(g(Y g)(4-1)), ako 4>0)
5·(4·(g(Y g) 3))
5·(4·(
λ n. (1, ako n = 0; i n·((Y g)(n-1)), ako n>0) 3))5·(4·(1, ako 3 = 0; i 3·(g(Y g)(3-1)), ako 3>0))
5·(4·(3·(g(Y g) 2)))
...
I tako dalje, rekurzivno evaluirajući strukturu algoritma. Svaka rekurzivno definirana funkcija se može shvatiti kao fiksna točka neke druge prikladne funkcije, i stoga, rabeći Y
, svaka rekurzivno definirana fukcija može biti ekspandirana kao lambda izraz. Posebice, sad se može čisto definirati oduzimanje, množenje i predikat usporedbe prirodnih brojeva na rekurzivan način.
Funkcija F: N → N
prirodnih brojeva je izračunljiva funkcija u N
, F(
x)
= y ako i samo ako f x == y
, gdje su x
i y
Churchevi numerali koji odgovaraju x i y, respektivno. Ovo je jedan od mnogo načina definicije izračunljivosti - vidi Church-Turingova teza za diskusiju drugih pristupa i njihovu istovjetnost.
Ne postoji algoritam koji kao ulaz prima dva lambda izraza i ispisuje na izlazu ISTINA
ili LAŽ
ovisno o tome jesu li ta dva izraza ekvivalentna ili ne. Ovo je povijesno prvi problem za koji je mogla biti dokazana nerješivost. Naravno, da bi se takvo nešto napravilo, pojam algoritma je trebao biti jasno definiran - Church je koristio definiciju preko rekurzivnih funkcija, za koju je poznato da je ekvivalentna svim ostalim razumnim definicijama pojma.
Churchev dokaz prvo svodi problem na određivanje ima li dani lambda izraz normalni oblik. Normalni je oblik ekvivalentni izraz koji ne može biti dalje reduciran. Potom pretpostavlja da je taj predikat izračunljiv, i stoga može biti izražen u lambda računu. Gradeći nad prethodnim radom Kleeneja i konstruiranjem Gödelovog pobrojanja za lambda izraze, konstruira lambda izraz e
koji usko prati dokaz Gödelovog prvog teorema nepotpunosti. Ako je e
apliciran na svoj vlastiti Gödelov broj, slijedi kontradikcija.
Kao što je istaknuo Peter Landin u svom klasiku iz 1965. A Correspondence between ALGOL 60 and Church's Lambda-notation, većina programskih jezika je ukorijenjena u lambda računu, koji pruža osnovne mehanizme proceduralne apstrakcije i proceduralne (potprogramske) aplikacije.
Implementiranje lambda računa na računalu uključuje tretiranje "funkcija" kao prvorazrednih objekata, što dovodi do implementacijskih problema za stogovno zasnovane programske jezika. Ovo je poznato kao Funarg problem.
Većina istaknutih primjena lambda računa u programiranju su funkcijski programski jezici, koji u suštini implementiraju račun proširen nekim konstantama i tipovima podataka. Lisp koristi varijantu lambda notacije za definiranje funkcija, ali samo njegov čisto funkcijski podskup ("čisti Lisp") je uistinu ekvivalentan lambda računu.
Funkcijski jezici nisu samo oni koji podržavaju funkcije kao prvorazredne objekte. Brojni imperativni jezici, npr. Pascal, već dugo podržavaju prosljeđivanje potprograma kao argumenata drugim potprogramima. U C-u i C-nalik podskupu jezika C++ je istovjetna funkcionalnost ostvarena prosljeđivanjem pokazivača kodu funkcija (potprograma). Takvi su mehanizmi ograničeni na potprograme koji su eksplicitno napisani u kodu, i ne podržavaju izravno funkcije višeg reda. Neki imperativni objektno orijentirani jezici imaju konstrukte koji predstavljaju funkcije bilo kojeg reda - takvi su mehanizmi dostupni u jezicima C++, Smalltalk te odnedavno i u Eiffelu ("agenti") i C# ("delegati"). Na primjer, Eiffel "inline agent" izraz
agent (x: REAL): REAL do Result := x * x end
označuje objekt koji odgovara lambda izraz
Sljedeći Python primjer koristi lambda Arhivirana inačica izvorne stranice od 9. lipnja 2007. (Wayback Machine) oblik funkcija:
func = lambda x: x * x
Ovo kreira novu anonimnu funkciju nazvanu func koja može biti prosljeđena drugim funkcijama, pohranjena u varijable, etc. Python također može tretirati bilo koju drugu funkciju stvorenu standardnom def Arhivirana inačica izvorne stranice od 8. lipnja 2007. (Wayback Machine) naredbom kao prvorazredni objekt.
Isto vrijedi za Smalltalk izraz
[ :x | x * x ]
Ovo je prvorazredni objekt (zatvaranje bloka) koji može biti pohranjen u varijable, prosljeđen kao argument itd.
Sličan C++ primjer (rabeći Boost.Lambda biblioteku):
for_each(v.begin(), v.end(), cout << _1 * _1 << endl;);
Ovdje standardna bibliotečna funkcija for_each iterira nad članovima vektora (ili liste) i ispisuje kvadrat svakog elementa. _1 oznaka je korištena u Boost.Lambda biblioteci za predstavljanje placeholder elemenata, predstavljenih kao x drugdje.
Jednostavan C# delegat koji prima varijablu i vraća kvadrat. Ova funkcijska varijabla potom može biti prosljeđena drugim metodama (ili funkcijskim delegatima)
// Deklariraj signaturu delegata
delegate double MatDelegat(double i);
// Kreiraj instancu delegata
MatDelegat f = delegate(double i) { return Math.Pow(i, 2); };
// Prosljeđivanje funkcijske varijable 'f' drugoj metodi, izvršujući
// i vraćajući rezultat funkcije
double Izvrsi(MatDelegat funkc)
{
return funkc(100);
}
Church-Rosserovo svojstvo lambda računa znači da se evaluacija (
Iako je nedeterministički lambda račun sposoban izraziti sve parcijalno rekurzivne funkcije, nije kadar izraziti sva računanja. Na primjer, nije sposoban izraziti neograničeni nedeterminizam (tj. za svaki se nedeterministički lambda izraz jamči terminacija - terminira u konačnom broju izraza). Međutim, postoje konkurentni programi za koje se jamči zaustavljanje i koji terminiraju u beskonačnom broju stanja [Clinger 1981, Hewitt 2006].
- Anonimna rekurzija
- Curry-Howard izomorfizam
- Knights of the Lambda Calculus
- Lambda kocka
- Prepisivanje
- SKI kombinatorni račun
- Sustav F
- Račun konstrukcija
- Tipizirani lambda račun
- Unlambda
- Abelson, Harold & Gerald Jay Sussman. Structure and Interpretation of Computer Programs. The MIT Press. ISBN 0-262-51087-1.
- Barendregt, Henk, The lambda calculus, its syntax and semantics, North-Holland (1984.), je ponajbolja referenca za (netipizirani) lambda račun; vidi također papir Introduction to Lambda Calculus Arhivirana inačica izvorne stranice od 28. svibnja 2007. (Wayback Machine).
- Barendregt, Henk, The Type Free Lambda Calculus str. 1091-1132 od Handbook of Mathematical Logic, North-Holland (1977.) ISBN 0-7204-2285-X
- Church, Alonzo, An unsolvable problem of elementary number theory, American Journal of Mathematics, 58 (1936), str. 345–363. Ovaj papir sadrži dokaz o neodlučivosti ekvivalentnosti lambda izraza.
- Clinger, William, Foundations of Actor Semantics. MIT Matematička doktorska disertacija, lipanj 1981.
- Punit,Gupta, Amit & Ashutosh Agte, Untyped lambda-calculus, alpha-, beta- and eta- reductions and recursion
- Henz, Martin, The Lambda Calculus. Formalno ispravan razvoj lambda računa.
- Hewitt, Carl, What is Commitment? Physical, Organizational, and Social Arhivirana inačica izvorne stranice od 11. veljače 2021. (Wayback Machine) COIN@AAMAS. 27. travnja 2006.
- Kleene, Stephen, A theory of positive integers in formal logic, American Journal of Mathematics, 57 (1935.), str. 153–173 i 219–244. Sadrži definicije nekoliko poznatih funkcija u lambda računu.
- Landin, Peter, A Correspondence Between ALGOL 60 and Church's Lambda-Notation, Communications of the ACM, vol. 8, no. 2 (1965.), stranice 89-101. Dostupno i sa ACM stranice. Klasični papir koji ističe važnost lambda računa kao baze programskih jezika.
- Larson, Jim, An Introduction to Lambda Calculus and Scheme Arhivirana inačica izvorne stranice od 6. prosinca 2001. (Wayback Machine). Nježni uvod za programere.
- L. Allison, Neki izvodivi primjeri
λ -računa - Chris Barker, Lambda tutorial Arhivirana inačica izvorne stranice od 14. lipnja 2007. (Wayback Machine) Neki jednostavni izvodivi Javascript primjeri i tekst.
- Georg P. Loczewski, The Lambda Calculus and A++
- Raùl Rojas, A Tutorial Introduction to the Lambda Calculus -(PDF)
- David C. Keenan, To Dissect a Mockingbird: A Graphical Notation for the Lambda Calculus with Animated Reduction Arhivirana inačica izvorne stranice od 12. lipnja 2007. (Wayback Machine)
- Bret Victor, Alligator Eggs: A Puzzle Game Based on Lambda Calculus