Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een...

29
Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de "machinetaal" bestaat uit reductiestappen. In principe kan men die in hardware realiseren (LISP machine). Het uit te voeren programma is één -expressie, die stapsgewijs gereduceerd wordt tot normaalvorm. De expressie kan als een string symbolen voorgesteld worrden, maar dat vereist veel kopieerwerk. Daarom gebruiken moderne implementaties een graph voorstelling. Dat maakt wel het memory-management moeilijker, en heeft geleid tot de ontwikkeling van allerlei technieken voor garbage collection. In de vorm die we totnogtoe gezien hebben zijn - conversie en -reductie nog te complex om als één stap gezien te worden, we vervangen ze door meer elementaire stappen.

Transcript of Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een...

Page 1: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Reductiemachine

Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de "machinetaal" bestaat uit reductiestappen. In principe kan men die in hardware realiseren (LISP machine). Het uit te voeren programma is één -expressie, die stapsgewijs gereduceerd wordt tot normaalvorm.

De expressie kan als een string symbolen voorgesteld worrden, maar dat vereist veel kopieerwerk. Daarom gebruiken moderne implementaties een graph voorstelling. Dat maakt wel het memory-management moeilijker, en heeft geleid tot de ontwikkeling van allerlei technieken voor garbage collection.

In de vorm die we totnogtoe gezien hebben zijn -conversie en -reductie nog te complex om als één stap gezien te worden, we vervangen ze door meer elementaire stappen.

Page 2: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

let en eval

Om het programmeren te vergemakkelijken voert men "syntactic sugar" toe, zoals de mogelijkheid om hulpfuncties te definiëren (let) en om de evaluatie expliciet te starten (eval)

staat voor:

let f = E1

let g = E2

eval E3

(f.(g.E3 E2) E1)

Page 3: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Graph voorstelling

Een -expressie wordt voorgesteld door haar parse tree, maar met extra pijlen die ervoor zorgen dat er cycli kunnen voorkomen. Dit betekent dat het originele programma gemakkelijk terug gereconstrueerd kan worden: in principe volstaat een depth-first doortocht van de parse tree.

Soorten knopen:

abstractie: x

applicatie: :

infix lijstconstructor: ,

lijst-einde of lege lijst: [ ]

numerieke waarde: #

variabele: x,y,z, ...

combinator: Y, true, false

operator: head, tail, cons, +, -, ...

indirectie: @

renaming: {z/x}

Page 4: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Graph voorstelling: voorbeelden

((x.y.(x (y x)) 2) [E,F])

y

:

,

,

[ ]

x 2

:

:

:

x

x

y

E

F

Page 5: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Graph voorstelling: voorbeelden

let fact = n.(((iszero n) 1) ((mult n) (fact (pred n))))

eval E

:

: :

:

nfact

:iszero

E

: 1

* n

pred

: :

n

n

Page 6: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

De regels

Voor -conversie en -reductie gebruikten we totnogtoe volgende regels.

-regel: x.E z.{z/x}E

-regel: (x.E Q) [Q/x]E

Daarnaast zijn er de regels voor lijsten en constante symbolen.

Omdat de expressies willekeurig complex kunnen zijn kan men het uitvoeren van die substituties niet als een elementaire stap opvatten. Daarom vervangen we deze regels door nieuwe, die wel elementaire stappen voorstellen. De regels voor lijsten worden iets sterker; we laten toe de applicatie van een lijst om te zetten in een lijst van applicaties - dit leidt tot de zgn. -regels.

Page 7: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Aangepaste regels

Voor -conversie:

1: {z/x}x z

2: {z/x}E E als x niet vrij in E

3: {z/x}y.E y.{z/x}E als x, y en z verschillend

4: {z/x}(E1 E2) ({z/x}E1 {z/x}E2)

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

De {z/x} wordt dus gewoon doorgeschoven naar binnen in de expressie.

Page 8: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Aangepaste regels

Voor -conversie:

1: (x.x Q) Q

2: (x.E Q) E als x niet vrij in E

3: (x.y.E Q) z.(x.{z/y}E Q) als x verschillend van y, en z

komt niet voor in E of in Q

4: (x.(E1 E2) Q) ((x.E1 Q) (x.E2 Q))

Voor 3: we willen (x.y.E Q) [Q/x]y.E maar alleen als y "veilig" is.

Dus beginnen we met y alvast te vervangen door een "verse" z. Omdat

die uiteraard verschillend is van x kunnen we de x naar binnen

schuiven, voorbij de z.

Page 9: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Aangepaste regels: de - regels

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

Voor lijsten vervangt men de regel

Door de zgn. -regels:

1: ([E1, ... ,En] Q) [(E1 Q), ... , (En Q)] en

2: x.[E1, ... ,En] [ x.E1 , ... , x.En ]

Deze regels, samen met die voor de combinatoren en operatoren, kunnen nu omgezet worden naar elementaire stappen voor de reductiemachine.

Page 10: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Stappen: -regels

{z/x}x z

{z/x}E E als x niet vrij in E

{z/x}y.E y.{z/x} E als xyz

y

z/x

x

z/x

z

x z/x

E

@

E

y

z/x

E

y

E

Page 11: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Stappen: -regels

{z/x}(E1 E2) ({z/x}E1 {z/x}E2)

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

z/x

:

E1 E2

:

:

E1 E2

,

,

A B

z/x

,

A B

z/x z/x

z/xz/x

Page 12: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Stappen: -regels

1: (x.x Q) Q

x

x

Q

:

x

x

Q

@

2: (x.E Q) E als x niet vrij in E

x

Q

:

E

x

Q

@

E

Page 13: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Stappen: -regels

3: (x.y.E Q) z.(x.{z/y}E Q)

als x en y verschillen, en z is vers: noch vrij, noch gebonden in (E Q)

y

x

Q

:

E

Q

y

x

E

z

x

z/y

:

Page 14: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Stappen: -regels

4: (x.((E1 E2) Q) ((x.E1 Q) (x.E2 Q))

x

Q

:

:

E1 E2

x

Q

:

:

E1 E2

:

x x

:

Page 15: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Stappen: -regels

1: ([E1, ... ,En] Q) [(E1 Q), ... , (En Q)]

, C

:

A B

, C

,

A B

: :

Page 16: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Stappen: -regels

2: x.[E1, ... ,En] [ x.E1 , ... , x.En ]

,

A B

x

,

A B

xx

,

Page 17: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

In plaats van de cyclische representatie te gebruiken, kunnen we ook de Y-combinator expliciet voorstellen, en volgende regel gebruiken.

Het gebruik van de cyclische representatie van recursieve functies blijkt gewoonlijk efficiënter te zijn.

Y combinator

:

Y

F

:

Y

F

:

Page 18: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Opmerkingen

• Ook voor de combinators null, +, head, ... zijn er uiteraard dergelijke operaties.

• De operaties behouden altijd de knopen aan de linkerkant (er kunnen nog andere pijlen zijn naar die knopen) en wijzigen enkel van de root het label. Op die manier is het duidelijk hoe het vervangen deel van de graph vasthangt aan de rest.

• De operaties voeren nooit nieuwe cycli in; de enige cycli zijn die veroorzaakt door recursieve definities.

Page 19: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Implementatie

Om de knopen voor te stellen gebruikt men bv. 4 velden :

( code, op1, op2, marker)

(marker voor de garbage collector).

Het herkennen van een patroon in een graph is in het algemeen een moeilijk probleem. Gelukkig zijn de te herkennen patronen hier erg klein. Om een -redex te vinden: gebruik een depth-first traversal om het volgende patroon op te sporen:

:

x

N1

N2

N3

Page 20: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Implementatie

Als N2 geen abstractieknoop is, dan is N1 niet de root van een -redex.

Anders, zoek een vrije occurence van x in de boom onder N3. Als er geen te vinden is, dan hebben we een 2-redex. Als er wel een gevonden wordt, dan bepaalt het veld code van N3 of we een redex voor 1, 3 of 4 herkennen. Als N3 noch een variable-, noch een abstractie-, noch een applicatieknoop is, dan is N1 niet de root van een -redex.

Het zoeken naar een vrije occurence van x voor herkennen van een 2-redex kan uitgevoerd worden in een depth-first doortocht.

Ook voor -redexen kunnen we volstaan met het onderzoeken van 2 knopen, met weer een extra test voor 2.

Page 21: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Evaluatie-orde

Doordat we nu andere regels hebben is normal order evaluatie niet meer helemaal wat we nodig hebben: bv

((x.y.E P) Q) (3)

(z.(x.{z/y}E P) Q) (4)

((z.x.{z/y}E Q) (z.P Q)) (3)

(v.(z.{v/x}{z/y}E Q) (z.P Q)) (4)

((v.z.{v/x}{z/y}E (z.P Q)) (v.Q (z.P Q))) ...

Afspraak: na 3 verder gaan met het deel na de nieuwe (meest linkse) .

Page 22: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Evaluatie-orde

Eager, applivative order: argumenten eerst.

Demand - driven: argumenten pas evalueren als nodig.

Lazy: ook de argumenten maar partieel evalueren als dat volstaat.

Normal order: meest linkse redex. In ons systeem komt dat overeen met lazy.

Lazy evaluatie is niet altijd efficiënt:

(x.((+ x)(pred x)) ((* 5) (succ 3))) (4) met Q = ((* 5) (succ 3))

((x.(+ x) Q) (x.(pred x) Q)) (4)

(((x.+ Q) (x.x Q)) (x.(pred x) Q)) (1, 2)

((+ ((* 5) (succ 3))) (x.(pred x) Q)) (regels voor *, succ)

((+ 20) (x.(pred x) Q)) ... en Q moet opnieuw geëvalueerd worden.

Page 23: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Graph reductie

De boom van Q = ((* 5) (succ 3)) wordt niet gedupliceerd:

3

:: :

:

:

: : 5

predx+ x

* succ

x 4

Page 24: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Graph reductie

3

:: :

:

:

: : 5

predx+ x

* succ

x

::

x x

Page 25: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Opmerkingen

•Deze reductiemachine kan uiteraard geperfectioneerd worden, bv, door parallellisme te gebruiken.

• Moderne implementaties halen de efficiëntie van een behoorlijke C compiler.

• I/O, of andere neveneffecten, kan men inbouwen door gebruik te maken van monads: interpreteer sommige symbolen m als acties; en bekijk paren (m,a), met m een actie en a een waarde. Er is een sequencing operatie >>= van type

m a ( a m b ) m b

Informeel: een actie die een a oplevert kan samengesteld worden met een functie die op basis van een a een actie geeft die een b oplevert. Het resultaat is een actie die een b oplevert.

Page 26: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Unificatie

In Haskell wordt pattern matching gebruikt in de definitie van functies, bv. in qsort: matching qsort [x:xs] met [3,2,4,1,5] resulteert in de binding van x aan 3 en van xs aan [2,4,1,5]. Ook by typechecking komt een dergelijke situatie voor: als men een functie f wil toepassen op een argument arg, dan moet de typedescriptor van f van de vorm td1 td2 zijn, en als arg typedescriptor tdarg heeft, dan moeten td1 en tdarg "gelijk gemaakt" kunnen worden, door vereenvoudigingen, maar ook door de vervanging van typevariabelen door meer concrete typedescriptoren. Dit "gelijk maken" (en tegelijk variabelen binden) noemt men unificatie

Ook in logische talen speelt unificatie een belangrijke rol.

Page 27: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Unificatie

qsort(cons(x , xs)) en cons(3 , cons(2 , cons(4 , cons(1 , cons(5 , [ ])))))

(in gewone mathematische notatie)

resultaat: x = 3 xs = cons(2 , cons(4 , cons(1 , cons(5 , [ ]))))

mult(add(4 , 5) , minus(y)) en mult(add(x ,y) , z)

resultaat: x = 4 y = 5 z = minus(5)

mult(add(4 , 5) , minus(y)) en mult(add(x ,y) , 8)

resultaat: fail

Page 28: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Unificatie: algemeen

Gegeven: twee termen, T1 en T2, opgebouwd uit

- variabelen

- constanten

- functie-applicaties ("Functoren", in logisch programmeren)

Gevraagd: een meest algemene unifier (most general unifier, MGU) voor T1 en T2

unifier: een substitutie (afbeelding van de variabelen naar de termen) die voldoet aan (T1) = (T2)

most general unifier: een unifier met de eigenschap dat, voor elke andere unifier ' , geldt dat '(T1) een instantie is van (T1), m.a.w. er is een substitutie die van

(T1) '(T1) maakt: ((T1)) = '(T1) (er geldt dan ook ((T2)) = '(T2) natuurlijk).

Page 29: Reductiemachine Functionele talen en dus de -calculus, worden vaak geïmplementeerd door een reductiemachine. De elementaire stap is een reductie, en de.

Unificatie: algoritme van Robinson

MGU = { };

WS = { (T1 , T2) }

repeat

verwijder een paar (R1 , R2) uit WS;

case

R1 en R2 zijn twee identieke variabelen of constanten: skip;

R1 is een variabele die niet voorkomt in R2:

vervang, overal in WS en MGU, R1 door R2;

voeg (R1 , R2) toe aan MGU;

R2 is een variabele die niet voorkomt in R1:

vervang, overal in WS en MGU, R1 door R2;

voeg (R1 , R2) toe aan MGU;

R1= f(y1, ... ,yn) en R2= f(z1, ... ,zn):

voeg {(y1,z1), ... ,(yn,zn)} toe aan WS

otherwise return(fail)

end case

until WS = { }