(Translated by https://www.hiragana.jp/)
Lambda-kalkulus – Wikipédia Ugrás a tartalomhoz

Lambda-kalkulus

Ellenőrzött
A Wikipédiából, a szabad enciklopédiából

A lambda-kalkulus (vagy λらむだ-kalkulus) egy formális rendszer, amit eredetileg matematikai függvények tulajdonságainak (definiálhatóság, rekurzió, egyenlőség) vizsgálatára vezettek be. Az elmélet kidolgozói Alonzo Church és Stephen Cole Kleene voltak az 1930-as években. Church, 1936-ban, a λらむだ-kalkulus segítségével bizonyította, hogy nem létezik algoritmus a híres Entscheidungsproblem (döntési probléma) megoldására. A λらむだ-kalkulus (akárcsak a Turing-gép) lehetővé teszi, hogy pontosan (formálisan) definiáljuk, mit is értünk kiszámítható függvény alatt.

A λらむだ-kalkulust nyugodtan nevezhetjük a legegyszerűbb általános célú programozási nyelvnek. Csak egyfajta értéket ismer: a függvényt (absztrakciót), és csak egyfajta művelet van benne: a függvény alkalmazás (változó-behelyettesítés). Ezen látszólagos egyszerűsége ellenére minden algoritmus, ami Turing-gépen megvalósítható, az megvalósítható tisztán a λらむだ-kalkulusban is. Ez az azonosság a λらむだ-kalkulus és a Turing-gép kifejező ereje (expressive power) között adja egyébként a Church–Turing-tézis alapját.

Míg korábban a λらむだ-kalkulus elsősorban a kiszámíthatóságelmélet (Theory of Computation) miatt volt érdekes, napjainkban ez már kevésbé hangsúlyos, és sokkal inkább a funkcionális programozási nyelvek elméleti és gyakorlati megalapozásában játszott jelentős, mondhatni központi szerepe került előtérbe.

A szócikk tárgya a λらむだ-kalkulus, eredeti, típus nélküli változata. A λらむだ-kalkulus bevezetése óta számos típusos lambda-kalkulus került kifejlesztésre, és valójában ezek a típusos változatok adják a mai funkcionális programozási nyelvek alapját.

Történelem

[szerkesztés]

Eredetileg Church célja egy olyan ambiciózus formális rendszer kidolgozása volt, amely segítségével a teljes matematikát tisztán formális alapokra lehetett volna helyezni. Ezt korábban már többen megpróbálták (többek között Gottlob Frege és Bertrand Russell), de nem jártak sikerrel. Amikor Church új rendszeréről is kiderült, hogy (hasonlóan Frege rendszeréhez) megfogalmazható benne a Russell-paradoxon, akkor döntött úgy, hogy a λらむだ-kalkulus (amely a rendszere részét képezte) önmagában is hasznos lehet kiszámíthatósági problémák vizsgálatára, és így önálló elméletként fejlesztette azt tovább.

Mit jelent a lambda?

[szerkesztés]

A görög lambda betű (λらむだ) csak jelölési konvenció a kötött változó megjelölésére az utána következő kifejezésben. A λらむだ használata általánosan elterjedt, bár egyes francia tudományos szövegekben mai napig használják a [x] jelölést a szokványosabb λらむだx helyett ha jelezni akarják, hogy az x változó kötött.

Jelenlegi formáját egy „evolúciós” folyamatnak köszönheti:

  1. Russell és Whitehead a Principia Mathematica-ban a kalap jelölést használta: t[â].
  2. Church módosította a jelölést: â.t[a], de ezt csak ∧a.t[a] formában tudták az akkori nyomdászok megjeleníteni.
  3. Végül egy újabb nyomdász kezében, valószínűleg tévedésből kialakult a végleges forma: λらむだa.t[a].

Informális bevezetés

[szerkesztés]

A λらむだ-kalkulus vizsgálatának tárgyai a λらむだ-kifejezések. A λらむだ-kifejezéseknek pontosan két fajtája létezik: λらむだ-absztrakció és alkalmazás.

λらむだ-absztrakció

[szerkesztés]

A λらむだ-kalkulusban a kétfajta kifejezés közül az egyik az absztrakció, vagy függvény. Vegyük például a következő egyszerű algebrai kifejezést: 3x + 5. Ha behelyettesítünk egy adott természetes számot az x változó összes előfordulási helyére, majd elvégezzük az algebrai műveleteket, akkor végeredményül egy természetes számot kapunk. x = 2 esetén például a kifejezés értéke 3*2 + 5 = 11 lesz. A kifejezés értéke tehát az x változó függvénye. Annak jelölésére, hogy ez így van, az x változót kiemeljük a kifejezés elé (absztraháljuk) és λらむだ-val jelöljük meg: λらむだx.(3x + 5). Az ilyen λらむだ-kifejezést λらむだ-absztrakciónak nevezzük és az x változót kötöttnek tekintjük. Mivel minden λらむだ-absztrakció tekinthető egy egyváltozós függvénynek is (jelen esetben az x változó függvényének) ezért a λらむだ-absztrakciót gyakran egyszerűen függvénynek nevezik. (Szigorúan véve ez a szóhasználat helytelen, hiszen nem minden függvény fejezhető ki λらむだ-absztrakcióval és nem minden λらむだ-absztrakció feleltethető meg függvénynek.[forrás?] Szerencsére a gyakorlati esetekben ez a megfeleltetés többnyire helytálló.) A λらむだ-absztrakcióval definiált függvények névtelen függvények lesznek, pontosabban a teljes λらむだ-kifejezés lesz a nevük.

Azon változókat, amelyeket egyetlen λらむだ sem köt, szabad változóknak nevezzük. Például a λらむだx.y kifejezésben az y szabad változó. A λらむだx.y kifejezést bármire alkalmazva mindig y-t kapunk eredményül.

Maga az „absztrakció” elnevezés valószínűleg abból a szokásból ered, hogy a matematikusok gyakran helyettesítenek bonyolultabb kifejezéseket egyszerűbbekkel, mondjuk egy új függvény bevezetésével, ily módon emelve az „absztrakciós szintet.”

Alkalmazás

[szerkesztés]

Az egyetlen művelet, amit egy λらむだ-absztrakcióval végezhetünk, az az alkalmazás (applikáció). Az alkalmazás jelölésére egyszerűen egymás mellé írjuk a λらむだ-absztrakciót és azt a λらむだ-kifejezést, amire alkalmazni akarjuk. Az így kapott λらむだ-kifejezést alkalmazásnak hívjuk. A fenti példánál maradva, λらむだx.(3x + 5) 12 azt jelenti, hogy alkalmazzuk a λらむだx.(3x + 5) függvényt 12-re. Fontos megérteni, hogy az alkalmazás a λらむだ-kalkulusban egyszerűen változó-behelyettesítést jelent: a λらむだx.(3x + 5) (z – 4) kifejezés eredménye az alkalmazás kiértékelése után 3(z – 4) + 5 lesz, amit úgy kapunk, hogy (z – 4)-et helyettesítünk az x változó összes előfordulási helyére a λらむだ-absztrakcióban. Az alkalmazás, akárcsak a hagyományos függvény alkalmazás, balra köt: f x y = (f x) y. Tehát az f függvényt először x-re alkalmazzuk, majd az alkalmazás eredményét (ami maga is egy függvény) alkalmazzuk y-ra.

Többváltozós függvények

[szerkesztés]

Többváltozós függvényeket egyváltozós függvények egymás utáni alkalmazásával definiálhatunk a λらむだ-kalkulusban (lásd még: currying.) Vegyük például a kétváltozós f(x,y) = x + y függvényt. Az ennek megfelelő λらむだ-kifejezés a következő: λらむだx.(λらむだy.(x + y)). Ha alkalmazni akarjuk ezt a kétváltozós függvényt a x = 4, y = 7 párra, azt a következő kifejezéssel tehetjük meg: λらむだx.(λらむだy.(x + y)) 4 7. Nézzük meg, hogyan néz ki ennek a kifejezésnek a kiértékelése, egymás utáni változó-behelyettesítéssel:

 λらむだx.(λらむだy.(x + y)) 4 7λらむだy.(4 + y)) 74 + 711

Magasabbrendű függvények

[szerkesztés]

Egy λらむだ-absztrakciót alkalmazhatunk másik λらむだ-absztrakcióra is (tehát a függvények alkalmazhatóak más függvényekre is).

Vegyük például a λらむだf.(λらむだz.(f (f z))) kifejezést, ami egy függvényre alkalmazva egy olyan kifejezést eredményez ami az f függvényt kétszer alkalmazza egymás után. Ha ezt a függvényt alkalmazzuk a korábbi λらむだx.(3x + 5) kifejezésre, akkor a következő kifejezést kapjuk: λらむだf.(λらむだz.(f (f z))) λらむだx.(3x + 5). Ha elvégezzük az f változó behelyettesítését, akkor az így kapott kifejezés λらむだz.(λらむだx.(3x + 5) (λらむだx.(3x + 5) z)) lesz. Nézzük meg mi történik, ha ezt az új kifejezést alkalmazzuk 2-re és egymás után elvégezzük a szükséges változó-behelyettesítéseket:

 λらむだz.(λらむだx.(3x + 5) (λらむだx.(3x + 5) z)) 2λらむだx.(3x + 5) (λらむだx.(3x + 5) 2)λらむだx.(3x + 5) (3*2 + 5)λらむだx.(3x + 5) (6 + 5)λらむだx.(3x + 5) 113*11 + 533 + 538

Az eredmény 38 amit akkor kapunk, ha az f(x) = 3x + 5 függvényt kétszer egymás után alkalmazzuk 2-re: f(f(2)) = 38. Tehát a λらむだf.(λらむだz.(f (f z))) kifejezés valóban két egymás utáni függvényalkalmazást definiál.

Kiértékelhetőség

[szerkesztés]

Az eddigi példákban a λらむだ-kifejezések mindegyikét ki lehetett értékelni, azaz olyan formára lehetett hozni, ahol nem maradt már „tennivaló” (elvégzendő művelet.) Ez nem minden λらむだ-kifejezésre igaz. Vegyük például a (λらむだx.x x) (λらむだx.x x) kifejezést. Ebben egy λらむだ-absztrakciót önmagára alkalmazunk. Ha megpróbáljuk kiértékelni, akkor azt tapasztaljuk, hogy a változó-behelyettesítés elvégzése után ugyanazt a kifejezést kaptuk vissza. Ennek a λらむだ-kifejezésnek (és még sok másiknak) nincs határozott értéke amihez véges kiértékelési (redukálási) lépésekkel eljuthatnánk.

„Tiszta” λらむだ-kalkulus

[szerkesztés]

A Church által definiált, „tiszta” λらむだ-kalkulusban nincs összeadás és kivonás, sem természetes számok (pontosabban, nincsenek előre definiálva), de bevezethetők mint egyes λらむだ-kifejezések rövidítései, ahogy azt később látni fogjuk.

Formális definíciók

[szerkesztés]

Legyen V változók megszámlálhatóan végtelen halmaza: V = {a, b, c, …, x, y, z, a1, b1, c1, …} és <változó>V. Ebben az esetben a λらむだ-kifejezések szintaxisát az alábbi környezetfüggetlen nyelvtan definiálja:

 <lambda-kifejezés>    →   <változó>             |
                           <lambda-absztrakció>  |
                           <alkalmazás>
 <lambda-absztrakció>  → (λらむだ<változó>.<lambda-kifejezés>)
 <alkalmazás>          → '(<lambda-kifejezés> <lambda-kifejezés>)

A jelölés könnyítése érdekében általában két konvenciót vezetnek be: (1) az alkalmazás balra köt és (2) a λらむだ-absztrakciót a lehető leghosszabban kiterjesztjük jobbra. Ezek a konvenciók lehetővé teszik, hogy sok esetben spóroljunk a zárójelekkel. Például a nyelvtan által generált ((λらむだx.(x x)) (λらむだy.y)) kifejezés helyett használhatjuk az egyszerűbb (λらむだx.x x) λらむだy.y kifejezést a félreértés veszélye nélkül.

Szabad és kötött változók

[szerkesztés]

Vizsgáljuk meg az f(x) = x + 5 egyváltozós függvényt. Ezt a függvényt tetszőleges számra alkalmazhatjuk és a függvény értéke minden esetben pontosan meghatározott: f(2) = 7, f(3) = 8. Vegyük azonban a g(x) = x + y + 5 függvényt. Ezt a függvényt alkalmazva egy számra csak egy újabb kifejezést kapunk, amiben marad egy ismeretlen változó: g(2) = y + 7, g(3) = y + 8. Ennek az az oka, hogy az y változó nem kötött a függvény definíciójában tehát a g függvény értéke nem csak az x váltózótól függ. A nem kötött változókat szabadnak nevezzük. Csak azt a λらむだ-absztrakciót tekintjük függvénynek, amely nem tartalmaz szabad változókat. Azt a λらむだ-kifejezést amelyik nem tartalmaz szabad változókat zártnak nevezzük. Annak eldöntésére, hogy egy λらむだ-kifejezés zárt-e vagy sem, definiálni kell mikor tekintünk egy változót kötöttnek. Informálisan, egy változó akkor kötött egy λらむだ-kifejezésben, ha tőle balra található egy λらむだ amelyik „kiterjed rá.” Például a λらむだx.x kifejezésben nincs szabad változó, míg a λらむだx.y kifejezésben az y szabad változó.

Formálisan, legyen FV(E) az E kifejezésben előforduló szabad változók (Free Variables) halmaza, amelyet a λらむだ-kifejezéseken az alábbi szerkezeti indukcióval definiálunk:

    FV(x) = {x}                    (változó)
FV(λらむだx.E) = FV(E) – {x}            (λらむだ-absztrakció)
FV(E1 E2) = FV(E1) ∪ FV(E2)        (alkalmazás)

Intuitíven, az E = λらむだx.x λらむだx.y kifejezésben egyetlen szabad változó van, y. Ugyanehhez az eredményhez eljuthatunk formálisan is, ha kiértékeljük az FV(E) kifejezést:

FV(E) =
FV(λらむだx.x λらむだx.y) =
FV(λらむだx.x) ∪ FV(λらむだx.y) =
(FV(x) – {x}) ∪ (FV(y) – {x}) =
({x} – {x}) ∪ ({y} – {x}) =
∅ ∪ {y} =
{y}

Egy λらむだ-kifejezés E zárt, ha FV(E) = ∅.

Változó-behelyettesítés

[szerkesztés]

Legyenek E és F tetszőleges λらむだ-kifejezések és v egy tetszőleges változó. Jelölje E[v ← F] azt a λらむだ-kifejezést, amit úgy kapunk E-ből, hogy v minden szabad előfordulását F-re cseréljük. Tehát (x + 4)[x ← 8] = (8 + 4) és (x + 4)[x ← (y - 3)] = ((y - 3) + 4).

A változó-behelyettesítés mechanikus végrehajtása kézenfekvőnek tűnik de néhány esetben egy kis körültekintésre van szükség különben nem helyes eredményt kapunk. Vegyük például a (λらむだx.y + 5) kifejezést amelyben y az egyetlen szabad változó. Intuitíve az egyes változók konkrét neve nem lényeges, ezért megtehetjük, hogy y-t átnevezzük mondjuk z-nek: (λらむだx.y + 5)[y ← z] = (λらむだx.z + 5). A kifejezés jelentése ettől az átnevezéstől még nem változott. Végezzük el azonban a következő behelyettesítést: (λらむだx.z + 5)[z ← x] = (λらむだx.x + 5). Az új kifejezésben már nincs egyetlen szabad változó sem, tehát a kifejezés jelentése megváltozott. Könnyű észrevenni, a gondot az okozta, hogy z egy olyan környezetben fordult elő amelyikben az x változó kötöttnek számít. Amikor z helyére x került, ez az új változó-előfordulás szabadból kötötté vált. Ezt a jelenséget nevezzük változó-elfogásnak (variable capture). Mivel a változó-elfogás megváltoztatja a λらむだ-kifejezés jelentését, ezért szeretnénk úgy definiálni a változó-behelyettesítést, hogy ezt a lehetőséget kiküszöböljük. A változó-behelyettesítés formális definíciójához szerkezeti indukciót használunk:

      x[v ← F]  =  F                         (x = v)
      x[v ← F]  =  x                         (x ≠ v)
(E1 E2)[v ← F]  =  E1[v ← F] E2[v ← F]
(λらむだx.E)[v ← F]  = (λらむだx.E)                    (x = v)
(λらむだx.E)[v ← F]  = (λらむだx.E[v ← F])            (x ≠ v és x ∉ FV(F))
(λらむだx.E)[v ← F]  = (λらむだz.E[x ← z][v ← F])     (x ≠ v és x ∈ FV(F) és z ∉ (FV(E) ∪ FV(F)))

A fenti szabályokból kiderül, hogy a változó-elfogást a kötött változó átnevezésével kerüljük el. A korábbi (λらむだx.z + 5)[z ← x] példa esetében például változó-elfogás fenyeget, ezért a kötött változót (jelen esetben x-et) le kell cserélnünk egy új változóra, amelyik nem okoz ütközést, mondjuk w-re. A behelyettesítés eredménye a formális szabályok szerint tehát (λらむだw.x + 5) lesz, azaz az x változó nem válik kötötté, mint a korábbi, naiv behelyettesítés esetén történt.

Szintaktikai egyezőség

[szerkesztés]

Két λらむだ-kifejezés szintaktikailag egyező (≡) ha pontosan ugyanazzal a karaktersorozattal írhatók le. Ezek alapján λらむだx.x ≡ λらむだx.x de λらむだx.x ≢ λらむだy.y. A szintaktikai egyezőség önmagában nem túl hasznos, de segít definiálni bonyolultabb konverziókat. Általában amikor azt mondjuk, hogy egy konverzió egy λらむだ-kifejezést egy másikba visz át, ezalatt azt értjük, hogy a konverzió végrehajtása után a két λらむだ-kifejezés szintaktikailag egyező.

αあるふぁ-konverzió

[szerkesztés]

Az intuíciónk azt súgja, hogy egy függvény (λらむだ-absztrakció) jelentése nem változik meg attól ha átnevezzük benne a kötött változókat. A λらむだx.(x + x) ugyanazt a függvényt definiálja, mint a λらむだy.(y + y) vagy a λらむだz.(z + z). Ez a felismerés motiválja az αあるふぁ-konverzió (alfa-konverzió) definícióját:

(λらむだx.E) →αあるふぁ (λらむだw.E[x ← w])       (w ∉ FV(E))
(E F) →αあるふぁ (E' F)                 (E →αあるふぁ E')
(E F) →αあるふぁ (E F')                 (F →αあるふぁ F')

Jelölje továbbá αあるふぁ* αあるふぁ-konverziók véges (akár nulla) hosszúságú sorozatát. Két λらむだ-kifejezés E és F αあるふぁ-ekvivalens (≡αあるふぁ), ha létezik αあるふぁ-konverziók olyan véges sorozata, amelyik az egyiket a másikba viszi át:

E ≡αあるふぁ F    ↔    E →αあるふぁ* E' ≡ F.

Ezentúl, ha azt mondjuk, hogy két λらむだ-kifejezés egyező, ezalatt mindig azt értjük, hogy αあるふぁ-ekvivalensek. Ennek az az oka, hogy az αあるふぁ-ekvivalencia egyszerűen a kötött változók átnevezgetését jelenti, ami érdemben nem befolyásolja a λらむだ-kifejezés jelentését. Tehát a (λらむだx.x) (λらむだy.y + y) és (λらむだz.z) (λらむだv.v + v) kifejezéseket egyezőnek tekintjük:

 (λらむだx.x) (λらむだy.y + y) →αあるふぁ 
 (λらむだz.z) (λらむだy.y + y) →αあるふぁ
 (λらむだz.z) (λらむだv.v + v) ≡ (λらむだz.z) (λらむだv.v + v)

βべーた-konverzió és βべーた-redukció

[szerkesztés]

A βべーた-konverzió (béta-konverzió) a függvény-alkalmazás elnevezése a λらむだ-kalkulusban. Amikor egy λらむだ-absztrakciót alkalmazunk egy λらむだ-kifejezésre, akkor a λらむだ-kifejezést behelyettesítjük a λらむだ-val kötött változó szabad előfordulásainak helyeire. Formálisan:

((λらむだv.E) F) →βべーた E[v ← F]

A βべーた-konverzió, akárcsak az αあるふぁ-konverzió, egy ekvivalencia-relációt definiál a λらむだ-kifejezéseken. A βべーた-konverzió, a látszat ellenére, szimmetrikus reláció. Vegyük például a (3 + 5) kifejezést. Ez βべーた-ekvivalens a (λらむだx.(x + 5)) 3 kifejezéssel, ami pedig βべーた-ekvivalens a (λらむだy.(λらむだx.(x + y))) 3 5 kifejezéssel.

A βべーた-konverzió aszimmetrikus változata a βべーた-redukció. A βべーた-redukció legfontosabb szerepe a λらむだ-kifejezések szisztematikus kiértékelésében van. A βべーた-redukció esetén mindig a „nyíl irányában” haladunk, azaz végrehajtjuk a kijelölt függvény-alkalmazásokat, ilymódon redukálva a λらむだ-kifejezést.

Egy λらむだ-kifejezésben egyszerre több alkalmazás is várhat kiértékelésre. Ezeket az alkalmazásokat redukálható részkifejezéseknek, röviden „redex”-nek (Reducible Expression) nevezzük. A βべーた-redukció definíciójában nincs megkötés arra, hogy ezeket milyen sorrendben kell elvégezni, de a választott sorrendnek jelentősége van. A választott kiértékelési sorrendet kiértékelési stratégiának nevezzük. Az alábbi λらむだ-kifejezés például két redexet is tartalmaz:

(λらむだx.(x + 5)) ((λらむだy.y) 2))

Az egyik redex maga a teljes kifejezés, míg a másik a (λらむだy.y) 2 részkifejezés. A βべーた-redukcióval tehát két „irányba” is továbbléphetünk. Példaképpen hasonlítsuk össze a két lehetséges βべーた-redukció eredményét:

((λらむだy.y) 2) + 5 βべーた (λらむだx.(x + 5)) ((λらむだy.y) 2)) βべーた (λらむだx.(x + 5)) 2

Az eredményül kapott kifejezések jelentősen eltérnek, de mindkettőben lehetőség van még további βべーた-redukció elvégzésére:

2 + 5 βべーた ((λらむだy.y) 2) + 5 βべーたβべーた (λらむだx.(x + 5)) 2 βべーた 2 + 5

Végeredményül mindkét esetben ugyanazt a kifejezést kaptuk, bár más lépések során jutottunk el hozzájuk. Az, hogy ez így történt, korántsem véletlen, hanem a λらむだ-kifejezések kiértékelésének alapvető tulajdonsága, amely a normál formákkal függ szorosan össze.

ηいーた-konverzió

[szerkesztés]

Legyen E egy λらむだ-kifejezés és x egy változó amelyik nem szabad E-ben. Ekkor az ηいーた-konverziót (eta-konverziót) az alábbi módon definiálhatjuk:

λらむだx.E x →ηいーた E             ( x ∉ FV(E) )

Intuitítven, az ηいーた-konverzió azt fejezi ki, hogy egy λらむだ-absztrakció jelentése nem változik meg attól, hogy „beburkoljuk” egy újabb λらむだ-absztrakcióba. Ennek az oka az, hogy egy tetszőleges F kifejezésre alkalmazva a „beburkolt” absztrakciót, egyetlen βべーた-redukciós lépéssel eljuthatunk az E F „eredeti” alkalmazáshoz amit akkor kapnánk, ha közvetlenül E-t alkalmaznánk F-re:

(λらむだx.E x) F βべーた
E F

Más szóval, mindegy, hogy E-t, vagy λらむだx.E x-t alkalmazzuk F-re, hiszen a βべーた-redukció elvégzése után ugyanazt az eredményt kapjuk.

Fontos, hogy az ηいーた-konverzióval „eldobott” változó ne legyen szabad E-ben, különben a kifejezés jelentése megváltozik. Például a λらむだx.x x kifejezésre nem alkalmazható az ηいーた-konverzió mert E = x tehát x szabad E-ben.

Normál forma

[szerkesztés]

Az a λらむだ-kifejezés amelyben nincs egyetlen redukálható részkifejezés sem, normál formában van. A λらむだ-kifejezések kiértékelésének célja tehát a normál forma elérése, egymás utáni βべーた-redukciókkal. Példák normál formában lévő λらむだ-kifejezésekre:

λらむだy.y
42
λらむだx.(λらむだy.x + y – 18)

λらむだ-kifejezések, amelyek még nincsenek normál formában:

(λらむだy.y) 7
(λらむだx.(λらむだy.x + y – 18)) 2 9
(λらむだx.(x + 5)) ((λらむだy.y) 2))

Nem minden λらむだ-kifejezés hozható normál formára. Vannak olyan esetek, amikor mindig marad redukálható részkifejezés így a βべーた-redukció a végtelenségig folytatható:

(λらむだx.x x x) (λらむだx.x x x) →βべーた
(λらむだx.x x x) (λらむだx.x x x) (λらむだx.x x x) →βべーた
(λらむだx.x x x) (λらむだx.x x x) (λらむだx.x x x) (λらむだx.x x x) →βべーた

Ezen λらむだ-kifejezésekre azt mondjuk, divergálnak és a jelölésükre egy speciális szimbólumot vezetünk be: . Ha azt szeretnénk kijelenteni egy λらむだ-kifejezésről, hogy divergál, akkor azt a következőképpen tehetjük meg:

(λらむだx.x x x) (λらむだx.x x x) = ⊥

Vannak olyan λらむだ-kifejezések, amelyek a kiértékelési stratégiától függően divergálnak vagy sem. Vegyük például a következő λらむだ-kifejezést és használjuk azt a kiértékelési stratégiát, amelyik mindig a legjobboldalibb redexet redukálja:

(λらむだy.8) ((λらむだx.x x x) (λらむだx.x x x)) →βべーた
(λらむだy.8) ((λらむだx.x x x) (λらむだx.x x x) (λらむだx.x x x)) →βべーた
(λらむだy.8) ((λらむだx.x x x) (λらむだx.x x x) (λらむだx.x x x) (λらむだx.x x x)) →βべーた

Ezzel szemben ha olyan kiértékelési stratégiát választunk amely mindig a legbaloldalibb redexet redukálja, gyorsan eljutunk a kifejezés normál formájához:

(λらむだy.8) ((λらむだx.x x x) (λらむだx.x x x)) →βべーた
8

A Church-Rosser tétel azt mondja ki (többek között), hogy ha egy λらむだ-kifejezésnek van normál formája, akkor ahhoz véges redukciós lépések sorozatával eljuthatunk, ha mindig a legbaloldalibb redukálható részkifejezést redukáljuk. (Ez az eredmény egyben egy kiértékelési algoritmust is ad a kezünkbe.) Ugyanezen okokból egyébként a lusta funkcionális programozási nyelvek is ezt a kiértékelési stratégiát használják.

További következménye a Church-Rosser tételnek, hogy ha egy λらむだ-kifejezés semmilyen kiértékelési stratégia mellett nem divergál, akkor bármilyen kiértékelési stratégiát választva ugyanahhoz a normál formához jutunk el.

A normál forma fogalmát felhasználva definiálhatjuk az azonosság fogalmát λらむだ-kifejezéseken: két λらむだ-kifejezés azonos, ha αあるふぁ-ekvivalens normál formára hozhatóak véges számú βべーた-redukciós lépéssel.

Természetes számok és alapműveleteik

[szerkesztés]

A λらむだ-kalkulus formális definíciójában nem szerepelnek sem a természetes számok, sem a rajtuk végzett alapműveletek (összeadás, szorzás stb.) Ezeket utólag, összetettebb λらむだ-kifejezések rövidítéseiként vezethetjük be. Fontos megjegyezni, hogy az alább következő definíciók jelentősége inkább elméleti, mintsem gyakorlati: a λらむだ-kalkulus kifejező erejét hivatottak bizonyítani. Azon programozási nyelvek amelyek a λらむだ-kalkulusra épülnek (funkcionális programozási nyelvek) a természetes számokat a nyelv részének tekintik és belső megvalósításukra alacsony szintű és hatékony primitíveket használnak.

A természetes számok bevezetésére a legelterjedtebb a Church egészek használata:

0 := λらむだf.λらむだx.x
1 := λらむだf.λらむだx.f x
2 := λらむだf.λらむだx.f (f x)
3 := λらむだf.λらむだx.f (f (f x))

Egy Church egész n tehát egy magasabbrendű függvényt definiál a λらむだ-kalkulusban amelyet egy egyváltozós függvényre f alkalmazva visszaadja annak n-edik hatványát. Például: 3 f →βべーた f3

A Church egészek definícióját felhasználva definiálhatjuk a rákövetkező (SUCCessor) függvényt amely n-re alkalmazva n+1-et ad:

SUCC := λらむだn.λらむだf.λらむだx.f (n f x)

Példa:

SUCC 1 :=
(λらむだn.λらむだf.λらむだx.f (n f x)) 1 βべーた
λらむだf.λらむだx.f (1 f x) :=
λらむだf.λらむだx.f ((λらむだf.λらむだx.f x) f x) βべーた
λらむだf.λらむだx.f ((λらむだx.f x) x) βべーた
λらむだf.λらむだx.f (f x) :=
2

Az összeadást (PLUS) az alább módon definiálhatjuk:

PLUS := λらむだm.λらむだn.λらむだf.λらむだx.m f (n f x)              ( m + n )

Példaképpen érdemes ellenőrizni, hogy a PLUS 2 1 kifejezés valóban 3-at ad eredményül:

PLUS 2 1 :=
λらむだm.λらむだn.λらむだf.λらむだx.m f (n f x) 2 1 βべーた
λらむだn.λらむだf.λらむだx.2 f (n f x) 1 βべーた
λらむだf.λらむだx.2 f (1 f x) :=
λらむだf.λらむだx.2 f ((λらむだf.λらむだx.f x) f x) βべーた
λらむだf.λらむだx.2 f ((λらむだx.f x) x) βべーた
λらむだf.λらむだx.2 f (f x) :=
λらむだf.λらむだx.(λらむだf.λらむだx.f (f x)) f (f x) βべーた
λらむだf.λらむだx.(λらむだx.f (f x)) (f x) βべーた
λらむだf.λらむだx.f (f (f x)) :=
3

A szorzást (MULTiplication) az összeadást felhasználva definiáljuk:

MULT := λらむだm.λらむだn.m (PLUS n) 0               ( m * n )

Informálisan, az n*m szorzat felfogható úgy is, mintha n-et m-szer hozzáadnánk 0-hoz.

Az alapműveletek bevezetését a fenti stílusban lehet folytatni, de a további definíciók némelyike már elég sok leleményességet igényel. Vegyük például a megelőző (PREDecessor) függvényt amely n-re alkalmazva n–1-et ad vissza:

PRED := λらむだn.λらむだf.λらむだx.n (λらむだg.λらむだh.h (g f)) (λらむだu.x) (λらむだu.u)   ( n – 1 )

Példaképpen érdekes ellenőrizni, hogy a fenti definíció valóban helyesen működik:

PRED 1 :=
(λらむだn.λらむだf.λらむだx.n (λらむだg.λらむだh.h (g f)) (λらむだu.x) (λらむだu.u)) 1 βべーた
λらむだf.λらむだx.1 (λらむだg.λらむだh.h (g f)) (λらむだu.x) (λらむだu.u) :=
λらむだf.λらむだx.(λらむだk.λらむだy.k y) (λらむだg.λらむだh.h (g f)) (λらむだu.x) (λらむだu.u) βべーた
λらむだf.λらむだx.(λらむだy.(λらむだg.λらむだh.h (g f)) y) (λらむだu.x) (λらむだu.u) βべーた
λらむだf.λらむだx.(λらむだg.λらむだh.h (g f)) (λらむだu.x) (λらむだu.u) βべーた
λらむだf.λらむだx.(λらむだh.h ((λらむだu.x) f)) (λらむだu.u) βべーた
λらむだf.λらむだx.(λらむだu.u) ((λらむだu.x) f) βべーた
λらむだf.λらむだx.(λらむだu.x) f βべーた
λらむだf.λらむだx.x :=
0

A PRED fenti definícójában a kulcs a (λらむだu.x) függvény, amely „eldob” egy függvényalkalmazást, így az eredeti n-edik hatvány helyett az n – 1-edik hatványt kapjuk, ami a Church egészek definíciója szerint pontosan a megelőző természetes szám lesz. További fontos tulajdonsága a PRED függvénynek, hogy nullára alkalmazva nullát ad eredményül, tehát a PRED függvény nem vezet ki a természetes számok halmazából.

A PRED függvény segítségével definiálhatjuk a kivonás (MINUS) műveletét:

MINUS := λらむだm.λらむだn.n PRED m            ( m – n )

Az m – n művelet felfogható úgy is, hogy m-re n-szer alkalmazzuk a megelőző (PRED) függvényt. A PRED függvény tulajdonságaiból következően ha egy nagyobb számot kivonunk egy kisebből, akkor nullát kapunk eredményül, tehát a MINUS függvény sem vezet ki a természetes számok halmazából.

Természetesen az osztás művelete is definiálható a λらむだ-kalkulusban, de ehhez előbb szükség lesz a rekurzív függvények bevezetésére.

Boole-algebra és predikátumok

[szerkesztés]

A logikai igazságértékeket (TRUE = igaz, FALSE = hamis) az alábbi módon szokás definiálni:

TRUE := λらむだu.λらむだv.u
FALSE := λらむだu.λらむだv.v

Mint minden kifejezés, így a logikai igazságértékek is csak függvények a λらむだ-kalkulusban: a TRUE függvény egyszerűen „eldobja” a második paraméterét, míg a FALSE függvény az első paraméterével teszi ugyanezt. Ez az ábrázolásmód eredetileg Churchtől származik, ezért a fenti függvényeket Church boolean-oknak is nevezik.

A Church booleanok segítségével definiálhatjuk a logikai műveleteket (AND = logikai és, OR = logikai vagy, NOT = tagadás):

AND := λらむだu.λらむだv.u v FALSE
OR := λらむだu.λらむだv.u TRUE v
NOT := λらむだb.λらむだu.λらむだv.b v u

Ellenőrzésképpen elvégezhetjük egy egyszerű logikai kifejezés kiértékelését:

AND TRUE FALSE :=
(λらむだu.λらむだv.u v FALSE) TRUE FALSE :=
(λらむだu.λらむだv.u v FALSE) (λらむだx.λらむだy.x) FALSE βべーた
(λらむだv.(λらむだx.λらむだy.x) v FALSE) FALSE βべーた
(λらむだx.λらむだy.x) FALSE FALSE βべーた
λらむだy.FALSE FALSE βべーた
FALSE

Ahhoz, hogy a későbbiekben programokat tudjunk írni a λらむだ-kalkulusban, szükségünk lesz egy függvényre, amellyel választani tudunk két különböző alternatíva között:

IFTHENELSE := λらむだb.λらむだu.λらむだv.b u v

A magyar szakirodalomban ezt a függvényt az előkelő vezérlési szerkezet néven nevezik, mert ez teszi lehetővé feltételes kifejezések írását. Ha az IFTHENELSE függvény első paramétere egy b Church boolean, akkor a kifejezés jelentése: HA b AKKOR u EGYÉBKÉNT v. Érdemes megemlíteni, hogy λらむだ-kalkulusban nincsenek utasítások, ezért a feltételes „utasítás” is csak egy függvény. A C programozási nyelvben járatosak számára hasznos analógia lehet a háromoperandusú feltételes kifejezésre gondolni: boolean-kifejezés ? kifejezés1 : kifejezés2.

Mielőtt nekivágnánk „valódi” programokat írni a λらむだ-kalkulusban, szükségünk lesz függvényekre, amelyek logikai teszteket végeznek el. Ezen függvényeket predikátumoknak nevezzük. A későbbiek szempontjából hasznos lesz egy olyan predikátumot definiálni, amelyikkel megvizsgálhatjuk, hogy egy adott természetes szám egyenlő-e nullával (n egy Church-egész):

ISZERO := λらむだn.n (λらむだx.FALSE) TRUE

Aki járatos valamennyire az Assembly programozási nyelvben, azt talán nem éri meglepetésként, hogy ennek az egyetlen predikátumnak a segítségével definiálhatóak a szokásos algebrai relációs műveletek a természetes számokon:

GT := λらむだx.λらむだy.NOT (ISZERO (MINUS x y))         ( x > y )
EQ := λらむだx.λらむだy.NOT (OR (GT x y) (GT y x))       ( x = y )
GE := λらむだx.λらむだy.OR (GT x y) (EQ x y)             ( x ≥ y )
LT := λらむだx.λらむだy.GT y x                           ( x < y )
LE := λらむだx.λらむだy.GE y x                           ( x ≤ y )

Irodalom

[szerkesztés]

Csörnyei Zoltán: Lambda-kalkulus. Typotex Kiadó, 2007. ISBN 978-963-9664-46-3

Kapcsolódó szócikkek

[szerkesztés]

Ha a λらむだ-kalkulusból „kivesszük” λらむだ-absztrakciót és csak az alkalmazást engedjük meg, akkor az így kapott rendszer kombinátor logika lesz.