Lambdakalkulus eller lambdakalkylen[trenger referanse] (også kjent som
-kalkylen) er et formelt system innenfor informatikk, logikk og matematikk utviklet av Alonzo Church i 1930-årene. Formålet var å undersøke fundamentet for matematikk, men Stephen Kleene og J.B. Rosser viste i 1935 at systemet er, logisk sett, inkonsistent. I 1940 presenterte Alonzo Church et typesystem for lambdakalkylen som gir opphav til et konsistent system, men som begrenser beregnbarhetsstryket betraktelig.
Senere ble systemet forsket med som et fundament for beregninger, og Alan Turing viste i 1937 at lambdakalkylen er turingkomplett. I dag er det i denne forbindelse den utypete lambdakalkylen er mest kjent. Se typeteori for typede varianter av lambdakalkylen.
Formell definisjon av termer
Termene til lambdakalkylen, i sin rene form, veldig enkle. Det er tre former for uttrykk: (1) variabler, (2) funksjoner, og (3) funksjonskall. Termene kan beskrives med en grammatikk som:
.
Hvor variablene
hentes fra mengden
, og mengden av alle termer kalles
. Termen
representerer funksjonskall, hvor
er funksjonen, og
er argumentet. Dette skrives gjerne som
i konvensjonell matte. Termen
representerer en funksjon som tar ett argument og binder det til
, for så å regne ut verdien til kroppen
. I konvensjonell matte kan man skrive dette som
. Termen
kalles ofte abstraksjon eller lambda-abstraksjon.
I utgangspunktet kan en term
tolkes på to måter,
og
. Men det er standard konvensjoner som sier:
- Applikasjon binder mot venstre, altså skal
tolkes som
. - Skopet for abstraksjon binder så langt til høyre som mulig. For eksempel skal
tolkes som
. - Flere etterfølgende
-abstraksjoner slås sammen: f.eks. er
en forkortelse for
.
Eksempler
Noen eksempler vi nå kan definere i den rene lambdakalkylen er:
, identitesfunksjonen
og
fra kombinatorisk logikk.
som tar en funksjon og et argument, og sender argumentet to ganger gjennom funksjonen.
Hvis vi beveger oss bort fra den rene lambdakalkylen og godtar konstanter for tall og operasjoner som pluss, kan vi definere funksjoner slik som:
, som er funksjonen som tar et tall og ganger med to.
, som kvadrere et tall.
Det er viktig å merke seg at
ikke er en del av den rene lambdakalkylen, men er bare ment for gi navn til termer i metaspråket.
Fri- og bundede variable
Lambda-abstraksjoner binder en variabel i skopet sitt. F.eks. i
, så bindes variablen
i termen
, men den bindes ikke i deltermen
. En variabel kan også forekommer fritt i en term: variabelen
er fri i termen
. En variabel kan både forekomme som bundet og fri i en term, men en gitt variabel på en gitt lokasjon i en gitt term er enten fri eller bundet, ikke begge deler.
Funksjonen
gir mengden av frie variabler som forekommer i en term, og er definert rekursivt over strukturen til termer, som:
![{\displaystyle {\textrm {FV}}(x)=\{x\}}](https://wikimedia.org/api/rest_v1/media/math/render/svg/195d46b9947086a0efa03f79e046b90335d160c7)
![{\displaystyle {\textrm {FV}}(N\,M)={\textrm {FV}}(N)\cup {\textrm {FV}}(M)}](https://wikimedia.org/api/rest_v1/media/math/render/svg/18a8ab03ff8bf216904494934e55891d48cb7d81)
![{\displaystyle {\textrm {FV}}(\lambda x.\,M)={\textrm {FV}}(M)\setminus \{x\}}](https://wikimedia.org/api/rest_v1/media/math/render/svg/cca38ea59d9f76d819b51a4721911c00f3400aa5)
Substitusjon
Substitusjon (eng: capture-avoiding substitution) er et viktig begrep i lambdakalkylen. Formålet med substitusjon er å bytte ut en variabel i en term med en annen term. For eksempel ønsker vi at det å bytte ut
med
i uttrykket
skal gi uttrykket
. I lambdakalkylen ønsker vi derfor å definere en funksjon
, som leses som bytt ut alle forekomster av
i
med
.
En naiv, tekstelig substitusjon vil bli feil, fordi variabler som forekommer fritt i
kan bli bundet hvis
settes rett inn i
. F.eks. vil
være feil, siden den tidligere frie variabelen
i
er blitt bundet i
.
I litteraturen beskrives flere måter å håndtere dette på. Den letteste måten er å definere substitusjon som en partiell funksjon som ikke gir noe svar dersom det blir navnekræsj, på følgende måte:
![{\displaystyle x[N/x]\equiv N}](https://wikimedia.org/api/rest_v1/media/math/render/svg/54aa06dac60be6a987b034540bdcc298b71b7f31)
når
og
er forskjellige ![{\displaystyle (M_{1}\,M_{2})[N/x]\equiv M_{1}[N/x]\;M_{2}[N/x]}](https://wikimedia.org/api/rest_v1/media/math/render/svg/f6fc692dda315b4aef131777d129c3e95dba3f35)
![{\displaystyle (\lambda x.\,M)[N/x]=\lambda x.\,M}](https://wikimedia.org/api/rest_v1/media/math/render/svg/7c49658d04d18160dee0383b6338b588ede748ca)
gitt at ![{\displaystyle y\not \in {\textrm {FV}}(N)}](https://wikimedia.org/api/rest_v1/media/math/render/svg/8baade67155f2abc82d726fc33e313e911b86e10)
En korrekt, total funksjon, endrer den siste regelen til:
hvor
,
og
er forskjellige, og
.
Omskrivningsregler
Termene vi definerte over har ikke blitt gitt noen formell mening. Historisk sett, så har det vært tre hovedregler som forteller hvordan man kan evaluere en term: alpha-konvertering (
), beta-konvertering (
) og eta-ekspansjon (
).
Nedenfor vil forskjellige relasjoner bli definert, men disse vil kun gjelde for toppen av en term, og kan ikke brukes på deltermer. Anta derfor at vi har en relasjon
på termer, og vi kan så definere relasjonen
som følger:
- hvis
, så ![{\displaystyle N\Rightarrow _{R}M}](https://wikimedia.org/api/rest_v1/media/math/render/svg/3693b772dbc0992c96bc3e5b2fab291ff7378aca)
- hvis
, så ![{\displaystyle \lambda x.\,N\Rightarrow _{R}\lambda x.\,M}](https://wikimedia.org/api/rest_v1/media/math/render/svg/ac800d097d784d22a1197b62bf3baf0f87ac685b)
- hvis
, så ![{\displaystyle N\,M_{1}\Rightarrow _{R}N\,M_{2}}](https://wikimedia.org/api/rest_v1/media/math/render/svg/d6c48b395374a6f89ca4a25249941972b4bda5e4)
- hvis
, så ![{\displaystyle N_{1}\,M\Rightarrow _{R}N_{2}\,M}](https://wikimedia.org/api/rest_v1/media/math/render/svg/2509af709fa358ac153d2cd6e8b0bea94da60633)
Relasjonen
er dermed relasjonen som gjør ett
-steg på en del-term av
.
Fra en relasjon
kan man definere relasjonen
som gjør null eller flere R-steg, som er den refleksive og transitive tillukningen av
. Og videre kan man definere
, som er den refleksive, symmetriske, transitive tillukningen av
.
Alpha-konvertering
Intuisjonen vår rundt variabler er at navnet til en lokal variabel er irrelevant, funksjonene
og
representerer samme funksjon. Alpha-regelen gjør det at man kan bytte om lokale navn formelt.
![{\displaystyle \lambda x.\,M\to _{\alpha }\lambda y.\,M[y/x]}](https://wikimedia.org/api/rest_v1/media/math/render/svg/893b273c934f5a931ab86e0de7e2365317b326f6)
gitt at
ikke forekommer fritt i
.
Med unntak av noen få, især de som jobber med implementasjoner av programmeringspråk, så er det vanlig å alltid jobbe med lambda-termer modulo alpha-ekvivalens, altså på ekvivalensklasser av relasjonen
.
Beta-reduksjon
Den viktigste regelen for lambdakalkylen er beta-reduksjon (
-redkusjon), som forteller hvordan en funksjon samhandler med et funksjonskall. Å kalle på en funksjon
med et argument
betyr at man setter inn argumentet
for variabelen
i kroppen,
, til funksjonen. Formelt skrives dette som:
![{\displaystyle (\lambda x.\,M)N\to _{\beta }M[N/x]}](https://wikimedia.org/api/rest_v1/media/math/render/svg/cb0f60cf8e0480a6be9dd78a9c6ff1fe9fa05e28)
hvor
er substitusjon av
for
i
.
En term
er på beta normalform hvis det ikke finnes noen
slik at
, og to termer
og
er beta-ekvivalente hvis
.
Eta-ekspansjon
Eta-ekspansjon handler om ekstensionalitet, og sier at alle funksjoner beskrives ved hjelp av lambda-abstraksjon og applikasjon. Formelt er regelen
![{\displaystyle M\to _{\eta }\lambda x.\,Mx}](https://wikimedia.org/api/rest_v1/media/math/render/svg/b7d18ba3615f22fc778c2ba59b71f9f94a97e13d)
hvor
ikke forekommer fritt i
.
Egenskaper ved lambdakalkylen
Lambdakalkylen er konfluent under beta-reduksjon. Mer presist: for alle
,
og
, hvis
og
, så eksisterer en
slik at
og
Lambdakalkylen er hverken svakt eller sterkt normaliserende (eng: weakly og strongly normalizing), ettersom f.eks. termen
ikke har noen beta normalform.
Koding av data
I den rene lambdakalkylen er det ingen data bortsett fra funksjoner. Det er likevel mulig å kode forskjellige datatyper som lambdatermer.
Sannhetsverdier
De bolske verdiene sann og usann kan kodes som følger:
![{\displaystyle \mathrm {SANN} \equiv \lambda x\,y.\;x}](https://wikimedia.org/api/rest_v1/media/math/render/svg/ae022a576fbd950b0236ad3439373da57b1fa176)
![{\displaystyle \mathrm {USANN} \equiv \lambda x\,y.\;y}](https://wikimedia.org/api/rest_v1/media/math/render/svg/8859600ca685a00bbe8411acf87025dc5a14ddc8)
![{\displaystyle \mathrm {IF} \equiv \lambda b\,c\,a.\;b\;c\;a}](https://wikimedia.org/api/rest_v1/media/math/render/svg/8fba120c70f97bf9191ee6f72ed5bf4e1826b58b)
Vi kan se at dette fungerer ved å se på hvordan
reduserer til
:
.
Ordnede par
Et par
sammen med to projeksjoner
og
kan defineres slik at
og
.
, hvor
er en forkortelse for
. ![{\displaystyle \mathrm {\pi _{1}} \equiv \lambda p.\;(\lambda \;x\;y.\;x)\;p}](https://wikimedia.org/api/rest_v1/media/math/render/svg/b31d40ed46534a9d14b0a24aaf1100afaa4d53bd)
![{\displaystyle \mathrm {\pi _{2}} \equiv \lambda p.\;(\lambda \;x\;y.\;y)\;p}](https://wikimedia.org/api/rest_v1/media/math/render/svg/0a6417abb39e5838a195523d21cd4820b0f5edc9)
Naturlige tall
I Churchs koding av naturlige tall, så representeres et tall
som termen
, hvor
er definert som
og
. Intuisjonen er at tall
representeres ved en iterator som gitt en funksjon og et startverdi vil kalle på funksjonen
ganger med startverdien.
Det er mulig å definere funksjoner slik som pluss, minus, gange, og relasjoner som sammenligner tall.
Litteratur
- H. P. Barendregt. Lambda Calculus, Its Syntax and Semantics. North Holland, 1985. ISBN 0444875085.
Oppslagsverk/autoritetsdata | Store Danske Encyklopædi · Encyclopædia Britannica · Stanford Encyclopedia of Philosophy · MathWorld · GND · LCCN · BNF · BNF (data) · SUDOC |
---|