- congruentie

32
- congruentie -regel: x.E z.{z/x}E, voor elke z die niet voorkomt in E. {z/x}E stelt hier het resultaat voor van de substitutie van z voor x in E. -congruentie: Twee expressies M en N zijn -congruent als ofwel M N, of M N, of N wordt verkregen uit M door een subexpressie S ervan te vervangen door een expressie T zo dat S T, of er is een expressie R zo dat M -congruent is

description

 - congruentie.  -regel :  x.E    z.{z/x}E , voor elke z die niet voorkomt in E. {z/x}E stelt hier het resultaat voor van de substitutie van z voor x in E.  -congruentie : - PowerPoint PPT Presentation

Transcript of - congruentie

Page 1: - congruentie

- congruentie

-regel:

x.E z.{z/x}E, voor elke z die niet voorkomt in E.

{z/x}E stelt hier het resultaat voor van de substitutie van z voor x in E.

-congruentie:

Twee expressies M en N zijn -congruent als ofwel M N, of M N, of N wordt verkregen uit M door een subexpressie S ervan te vervangen door een expressie T zo dat S T, of er is een expressie R zo dat M -congruent is met R en R is -congruent met N.

Page 2: - congruentie

- converteerbaarheid

-regel: (x.P Q) [Q/x]P waar [Q/x]P het resultaat is van de substitutie van Q voor x in P, rekening houdend met het feit dat er eventueel nieuwe gebonden namen ingevoerd worden.

Een expressie M is -converteerbaar (gelijk) aan een expressie N, N = M, als N -congruent (zie verder) is met M, of M N, of N M, of er is een -expressie E zodat M = E en E = N.

De zo verkregen relatie = is uiteraard een equivalentierelatie. staat voor 0 of meer reductiestappen ( of ).

Page 3: - congruentie

Church - Rosser stelling

In het algemeen zijn er in een -expressie meerdere redexen, d.w.z. subtermen van de vorm (x.P Q) die in aanmerking komen voor -reductie. Dus stelt zich de vraag of het kan dat een -expressie meer dan één normaalvorm heeft: schematisch

-expressie

... ...

normaalvorm_1 normaalvorm_2

Page 4: - congruentie

Church - Rosser stelling

Dat is natuurlijk niet wenselijk, tenminste als de 2 normaalvormen echt verschillen. De Church-Rosser stellingen drukken uit dat het fenomeen zich niet voordoet.

Stelling (Church-Rosser 1): Voor -expressies A, B en C: als A B en A C dan bestaat er een -expressie D zo dat

Gevolg: Als A B en A C, en B en C zijn beide in normaalvorm, dan zijn B en C -congruent.

B C

A

D

"Diamond property"

één stap

evt. meerdere stappen

Page 5: - congruentie

Church - Rosser stelling

Stelling (Church-Rosser 2): Als A en B -converteerbaar zijn in elkaar, dan is er een D met A D en B D.

Er bestaat dan een "zigzag-lijn" van reducties en -stappen, van A naar B A

B

• Als A = B (-converteerbaar) en B is in normaalvorm, dan A B

• Als A = B, dan hebben ze ofwel beide dezelfde normaalvorm, ofwel hebben ze er geen van beide een.

Gevolg:

Page 6: - congruentie

Church - Rosser stelling

Helaas lost dit niet alle problemen ivm de evaluatievolgorde op: er zijn ook nog de -expressies die tot een oneindige reeks reducties leiden, zoals (x.(x x) x.(x x)):

(x.(x x) x.(x x))

(x.(x x) x.(x x)) ...

Page 7: - congruentie

Reductiestrategieën

Als men bv een dergelijke expressie als argument gebruikt van een applicatie krijgt men een situatie waarin er eventueel wel een normaalvorm is, maar ook oneindige reducties:

((a.b.b (x.(x x) x.(x x))) x.x) (b.b x.x) x.x

maar eerst het argument (x.(x x) x.(x x)) van a.b.b evalueren levert een oneindige reeks reducties op, zoals gezien.

Page 8: - congruentie

Normal order - Applicative order

Bij de evaluatie van een functieapplicatie f(arg) gebruikt men in imperatieve talen gewoonlijk de applicatie orde: eerst wordt het argument uitgewerkt, en daarna wordt f erop toegepast (call-by-value). In de -calculus, en de functionele talen die erop gebaseerd zijn, gebruikt men gewoonlijk de normal order evaluatie: bij het evalueren van (f arg) beginnen we met de applicatie, dus als f = x.B is dat de reductie

(x.B arg) [arg/x]B

(waar [arg/x]B staat voor de versie van B na de substitutie van arg voor x). Het doet er niet toe dat er binnen B eventueel nog redexes zijn.

Page 9: - congruentie

Normal order evaluatie

In het algemeen reduceert men bij normal order evaluatie telkens de meest linkse redex: die met het meest linkse beginsymbool (.

bv: (z and (select_second t)) toegepast op z = true en t = false

(z.(t.((x.y.((x y) false) z) (x.y.y t)) true) false)

(t.((x.y.((x y) false) false) (x.y.y t)) true)

((x.y.((x y) false) false) (x.y.y true))

Dit noemt men ook lazy evaluation: je begint maar aan het argument als het echt nodig is.

4 mogelijkheden

Page 10: - congruentie

Normal order evaluatie

Stelling (standardization): Als een -expressie een normaalvorm heeft, dan is haar normal order evaluatie eindig.

Nadeel: normal order evaluatie kan erg inefficiënt zijn, omdat een gebonden variabele meerdere keren kan voorkomen in een -expressie.

(x.((plus x) x) (succ 5))

((plus (succ 5)) (succ 5))

(succ 5) wordt 2 keer geëvalueerd

Page 11: - congruentie

Combinators

Zoals we al zagen by de numerals, booleans enz. hebben combinators, -expressies zonder vrije variabelen (ook wel gesloten -expressies genoemd), de eigenschap dat hun betekenis niet afhangt van de context, dwz van de grotere expressie waarvan ze eventueel een subexpressie zijn. Als er daarentegen wel vrije variabelen zijn worden die evt. bij applicatie vervangen door een argument, dat dan op zijn beurt kan interageren met de rest van de expressie.

Men kan nu proberen combinators te vinden die van speciaal belang zijn bij de implementatie van de -calculus. Het gaat dan om combinators die hogere orde - functies voorstellen.

Page 12: - congruentie

Combinators

Identiteit: I x.x

Functiecompositie: compose f.g.x.(f (g x))

Functieapplicatie: apply f.x.(f x)

Compose is een voorbeeld van een zgn curried operator: om een functie van 3 argumenten voor te stellen worden functies van één argument in elkaar genest. Je kan met behulp van de gewone reductieregel nagaan dat compose inderdaad associatief is, dat dus geldt:

((compose ((compose f) g)) h) = ((compose f) ((compose g) h))

Page 13: - congruentie

Combinators

Speciale symbolen die staan voor combinators, zoals I en compose,kunnen op twee manieren gebruikt worden:

• gewoon als afkorting van hun definitie; we moeten dan niets veranderen aan de reductieregel(s), of

• als nieuwe atomen, dus constante symbolen, die niet verder opgesplitst worden. Dan kunnen we er alleen mee werken als we er specifieke, nieuwe reductieregels voor invoeren. Dit kan de efficiëntie sterk verbeteren, en het is bv wat we doen voor de combinators die getallen voorstellen.

Nieuwe regels voor I, compose en apply:

(I)E E (((compose F) G) E) (F (G E)) ((apply A) B) (A B)

Page 14: - congruentie

Combinators: uitgebreide syntax

Om het gewone rekenen met getallen en booleans in te voeren breiden we de syntax uit als volgt:

< expression > ::= < constant > | < name > | < function > | < application >

...

< constant > ::= < number > | < operator > | < combinator >

< number > ::= < integer > | < real number >

< operator > ::= < arithmetic operator > | < relational operator > | < boolean operator > | < predicate >

< arithmetic operator > ::= + | - | ...

< predicate > ::= zero

< combinator > ::= true | false | I | compose

...

Page 15: - congruentie

Recursie: de Y-combinator

Recursieve definitie van faculteit, in gewone notatie:

fac(n) == if n = 0 then 1 else n * fac(n-1)

in -notatie:

(fac n) = (((iszero n) 1) ((mult n) (fac (pred n))))

en dus

fac = n.(((iszero n) 1) ((mult n) (fac (pred n))))

en

fac = (f.n.(((iszero n) 1) ((mult n) (f (pred n)))) fac),

wat van de vorm f = (E f) is. Bijgevolg komt fac bepalen erop neer een fixpunt te zoeken van de functie voorgesteld door

f.n.(((iszero n) 1) ((mult n) (f (pred n)))).

Page 16: - congruentie

iszero

De test voor nul, iszero, kan voorgesteld worden als

n.((n (true false)) true).

Toepassing op 0 = f.x.x :

(n.((n (true false)) true) f.x.x)

((f.x.x (true false)) true)

(x.x true)

true

Page 17: - congruentie

iszero

Toepassing op 2 = f.x.(f (f x)):

(n.((n (true false)) true) f.x.(f (f x)))

((f.x. (f (f x)) (true false)) true)

(x.((true false) ((true false) x)) true)

((true false) ((true false) true))

== ((x.y.x x.y.y) ((true false) true))

((z.y.z x.y.y) ((true false) true)) (-conversie)

(y.x.y.y ((true false) true))

(z.x.y.y ((true false) true)) (-conversie)

x.y.y

== false

Page 18: - congruentie

De Y combinatorTerug naar recursie. We zoeken een fixpunt van een functie E, die zelf op functies werkt. Dat blijkt te kunnen door toepassing van de combinator Y, ook wel fixpuntcombinator of paradoxale combinator genoemd:

Y == y.(x.(y (x x)) x.(y (x x)))Dit is een aangepaste versie van de (x.(x x) x.(x x)) van voordien, alleen wordt er bij elke iteratie een applicatie van y op (x x) neergezet:

(y.(x.(y (x x)) x.(y (x x))) E)

(x.(E (x x)) x.(E (x x)))

(E (x.(E (x x)) x.(E (x x))))

(E (E (x.(E (x x)) x.(E (x x))))) enzovoort

Page 19: - congruentie

de Y combinator

(Y E) reduceert dus wel degelijk tot (E (Y E)). De body van de recursieve definitie wordt een willekeurig groot aantal keer herhaald. Als er in E geen basisgeval voorkomt (zoals het geval n=0 bij fac) dan levert ook de Y combinator uiteraard geen praktische oplossing:

bv. x = 3x - 10 we zoeken een functie g bepaald door

g = (x.(minus ((mult 3) x) 10) g)

met de Y combinator: g = (Y f.x.(minus ((mult 3) x) 10)).

De rechterkant, toegepast op een argument, geeft aanleiding tot een oneindige reductie. Als er een basisgeval is, dan stopt de reductie wel.

Page 20: - congruentie

Y combinator : eindige recursie

bv. fac: de n samen met de iszero zorgen ervoor dat de reductie stopt.

(fac 1) == ((Y E) f.x.(f x)) waar E == f.n.(((iszero n) 1) ((mult n) (f (pred n))))

((Y E) f.x.(f x)) == ((y.(x.(y (x x)) x.(y (x x))) E) 1) ((x.(E (x x)) x.(E (x x))) 1) ((E (x.(E (x x)) x.(E (x x))) 1) == ((f.n.(...) (x.(E (x x)) x.(E (x x))) 1) (n.(((iszero n) 1) ((mult n) ((x.(E (x x)) x.(E (x x))) (pred n)))) 1)

(((iszero 1) 1) ((mult 1) ((x.(E (x x)) x.(E (x x))) (pred 1)))) (iszero 1) geeft false, we gaan verder met ((mult 1)... (pred 1)...

((mult 1) (n.(...) ) 0) (iszero n) geeft nu true en de recursie stopt.

Page 21: - congruentie

Curry's paradox

De gewone logische eigenschappen van implicatie zijn inconsistent met de interpretatie van -reductie als gelijkheid

De logische formule (§): (P (P Q)) (P Q) is waar. Verder geldt de regel Modus Ponens: als P en P Q waar zijn, dan is ook Q waar.

Bekijk nu de -expressie voor (§): imp is de combinator voor implicatie

((imp ((imp P) ((imp P) Q))) ((imp P) Q))

en stel N == x.((imp x) ((imp x) Q)) voor willekeurige Q (x (x Q))

en P == (Y N) dus P is het fixpunt van N, dwz P = (N P)

dan geldt P = (N P) = ((imp P) ((imp P) Q) en substitutie in (§) geeft

((imp ((imp P) ((imp P) Q))) ((imp P) Q)) = ((imp P) ((imp P) Q)

= (N P) = P . Dus (§) = P.

Page 22: - congruentie

Curry's paradox

Aangezien (§) waar is, is P = true. Maar P staat voor (P (P Q)), dus zijn ook (P Q) en dus Q waar. Maar Q was willekeurig, dus we hebben een contradictie.

De oorzaak van de inconsistentie ligt in het zonder beperking toelaten van zelf-applicatie. Dit kan opgelost worden door het toevoegen van typering: aan elke -expressie wordt een type toegekend. Als de types T en TT verschillen, dan kan een functie van type TT niet op zichzelf toegepast worden.Deze idee leidde tot de getypeerde - calculus.

Page 23: - congruentie

De -regel

Abstractie is een partieel inverse van applicatie: er geldt (x.P x) Pmaar, met abstractie en applicatie in de andere volgorde, is x.(P x)niet reduceerbaar tot P. Applicatie hiervan op een term Q kan ertoe leiden dat er vrije voorkomens van x in P onder de x terecht komen, en daarom reduceert (x.(P x) Q) tot ([Q/x]P Q), wat in het algemeen niet hetzelfde is als (P Q). Nochtans lukt het wel als we voor de abstractie een verse variabele gebruiken:voor elke twee termen P,Q en variabele x, met x niet vrij in P, geldt (x.(P x) Q) (P Q).Dus zijn x.(P x) en P extensioneel equivalent (als functie dus) terwijl ze toch een verschillende normaalvorm hebben. Om de -calculus extensioneel compleet te maken (dwz als termen extensioneel equivalent zijn dan hebben ze dezelfde normaalvorm) voegen we een reductieregel toe.

Page 24: - congruentie

De -regel

<naam> . (<expressie> <naam>) mag vereenvoudigd worden tot <expressie> , m.a.w. we nemen als nieuwe, extra regel:

( <naam> . (<expressie> <naam>) <argument> )

(<expressie> <argument>)

Page 25: - congruentie

Standaard combinators

Het is mogelijk om elke -expressie te vervangen door een equivalente expressie die enkel bestaat uit combinators, constanten, en vrije variabelen die op mekaar toegepast zijn. Als, bv, u en v de enige vrije variabelen in P zijn, dan geldt voor de combinator u.v.P dat

((u.v.P u) v) = P.

Het blijkt mogelijk te zijn om helemaal van de abstracties (en dus van de gebonden variabelen) af te komen en een versie van de -calculus te maken met slechts twee combinatoren: de standaard combinatoren S en K. (Schönfinkel, Curry)

Page 26: - congruentie

Standaard combinators

S en K zijn gedefinieerd als volgt:

S: x.y.z.((x z) (y z))

K: x.y.x (= True)

Als shorthand kunnen we de identiteit I: x.x gebruiken, ze is niet echt nodig want ((S K) K) = I

Een expressie met enkel de standaard combinators heet een standaard combinator expressie.

< comb-expression > ::= < atom > | < application >

< atom > ::= < variable > | < constant > | < combinator >

< application > ::= (< comb-expression > < comb-expression >)

< combinator > ::= S | K

Syntax:

Page 27: - congruentie

Standaard combinators

Stelling: Voor elke -expressie E kan men een standaard combinator expressie F construeren met F = E.

Deze constructie staat bekend als “bracket abstraction”. Combinator expressies staan dichter bij het practische functionele programmeren dan de -calculus: je vertrekt daar immers ook met een aantal vaste basisfuncties, en de nieuwe regels zijn ook efficiënter dan de -reductie. Er zijn naast S en K nog een heel aantal vergelijkbare combinatoren ingevoerd. Omgekeerd kunnen die combinatoren steeds terug vertaald worden in -calculus, zodat de theoretische basis aanwezig blijft.

Page 28: - congruentie

Lijsten in de -calculus

Een lijst [E1, E2, ... , En] kan in de -calculus voorgesteld worden als

z.((z E1) z.((z E2) ... z.((z En) nil)...)

met nil een constant symbool dat de lege lijst voorstelt. Men neemt dan head == x.(x true), tail ==x.(x false) en cons == x.y.z.((z x) y). Men moet dan geen extra notatie invoeren. Een beknopter alternatief bestaat erin de syntax uit te breiden met lijstexpressies van de vorm

[E1, E2, ... , En],

met nieuwe symbolen voor combinatoren als head, tail en cons, en daar gepaste reductieregels voor te geven.

Page 29: - congruentie

Lijsten: syntax

< -expression > ::= < variable> | … | < list > < list > ::= [ < -expression > < list-tail > | [ ]

< list-tail > ::= , < -expression > < list-tail > | ]

< list-operator > ::= head | tail | cons

De syntax voor -expressies wordt als volgt uitgebreid:

We kunnen nu expressies schrijven als bv. (q.[p,q,r] A) , (x.[(x y),(y x)] B) of (x.(y.[x,y] a) [b,c,d]), en we verwachten dat die reduceren tot respectievelijk [p,A,r] , [(B y),(y B)] en [[b,c,d],a] .

Page 30: - congruentie

Lijsten: reductieregels

(head [ ]) [ ] (head [E1, ... ,En]) E1

(tail [ ]) [ ] (tail [E1, ... ,En]) [E2, ... ,En]

((cons A) [ ]) [A] ((cons A) [E1, ... ,En]) [A,E1, ... ,En ]

(null [ ]) true (null [E1, ... ,En ]) false

(1 [E1, ... ,En ]) E1 (k [E1, ... ,En ]) ((pred k) [E2, ... ,En ])

Page 31: - congruentie

Lijsten: reductieregels

Ook de regels voor -conversie en -reductie moeten dus uitgebreid worden:

{z/x} [E1, ... ,En] [{z/x}E1, ... , {z/x}En]

(x.[E1, ... ,En] Q) [(x.E1 Q), ... , (x.En Q)]

Page 32: - congruentie

Wederzijdse recursie

Met behulp van lijsten kunnen we ook hiervoor de Y combinator gebruiken.

Stel, we hebben een rij functiedefinities f1 = e1, ... , fn = en. Stel dat de fi

overal in de ej mogen voorkomen. De waarde van een expressie E die de fi

gebruikt kan niet zomaar verkregen worden door reductie van (f1.( ... (fn.E en) ... )) want een vrij voorkomen van fi in ej wordt dan maar vervangen als i < j.

We gebruiken een F die de lijst [f1, ... , fn] voorstelt. Meer precies, laat Ri de expressie zijn bekomen uit ei door de vrije voorkomens van de fk in ei te vervangen door (k F), d.w.z. de selectie van het k-de element uit F. Dan

F = [R1, ... , Rn]

Dus F = (g.[r1, ... , rn] F) waar de ri bekomen zijn uit de Ri door F te vervangen door g. We hebben nu weer

F = (Y g.[r1, ... , rn])