0.1 inhalte und vorspann - ki.informatik.uni-frankfurt.de · concurrent haskell und chf ans atze zu...

50
SAFP, WS 2014/15, Striktheits-Analyse, 30. Januar 2015 1 0.1 Inhalte und Vorspann Pr¨ ufungen sind m¨ undlich. Ziele SAFP: Allgemein: operational basierte Programmanalysen; und kontextuelle Gleichheit. Beherrschen der Techniken und Verst¨ andnis der Grundlagen. Inhalte SAFP: KFPTS und KFP, Wiederholung. Improvement Theorie (Optimierungen) Striktheitsanalyse in KFPTS+seq und Striktheitstableaus. Anwendungen: z.B. Implizite Parallelisierung Letrec Kalk¨ ul LR Striktheitsanalyse in LR Abstrakte Interpretation (denotational): Striktheitsanalyse Spezielle abstrakte Interpretation Wadler’s 4 Punkt Domain. Concurrent Haskell und CHF Ans¨ atze zu einer operationalen Analyse. Polymorphe Spracherweiterungen (mittels System-F ) (Zwischencode Has- kell) und operationale Analyse

Upload: dinhliem

Post on 14-Aug-2019

214 views

Category:

Documents


0 download

TRANSCRIPT

SAFP, WS 2014/15, Striktheits-Analyse, 30. Januar 2015 1

0.1 Inhalte und Vorspann

Prufungen sind mundlich.

Ziele SAFP:

• Allgemein: operational basierte Programmanalysen; und kontextuelleGleichheit.

• Beherrschen der Techniken und Verstandnis der Grundlagen.

Inhalte SAFP:

• KFPTS und KFP, Wiederholung.

• Improvement Theorie (Optimierungen)

• Striktheitsanalyse in KFPTS+seq und Striktheitstableaus.

• Anwendungen: z.B. Implizite Parallelisierung

• Letrec Kalkul LR

• Striktheitsanalyse in LR

• Abstrakte Interpretation (denotational): StriktheitsanalyseSpezielle abstrakte Interpretation Wadler’s 4 Punkt Domain.

• Concurrent Haskell und CHF Ansatze zu einer operationalen Analyse.

• Polymorphe Spracherweiterungen (mittels System-F ) (Zwischencode Has-kell) und operationale Analyse

Kapitel 1

Semantik und Analyse:insbesondereStriktheitsanalyse

1.1 Kernsprachen, Reduktion und Eigenschaf-ten

1.1.1 Funktionale Kernsprache KFPTS

Die ungetypte Kernsprache KFPTS soll als Grundlage fur Analysen dienen, ins-besondere fur eine Striktheitsanalyse und deren Anwendung. Die Demandana-lyse ist eine Erweiterung, die wir nicht behandeln werden. Die Sprache KFPTSist zwar ungetypt, aber kennt Konstruktoren mit fester Stelligkeit und Typen,wobei nur das case-Konstrukt durch Typen beschrankt ist.Eine einfache kontextfreie Grammatik fur KFPTS-Ausdrucke (Terme, Expres-sions) ist:

Definition 1.1.1 Es gibt eine Menge von Typsymbolen und Konstruktor-symbolen c, jeder Konstruktor c hat eine Stelligkeit ar(c), und ist genau einemTyp zugeordnet. Ebenso eine Menge von Superkombinatorsymbolen mit Stellig-keit.

2

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 3

EXP ::= Variable | λV . EXP wobei V eine Variable ist.::= Superkombinatorname

| (Konstruktor EXP1 . . . EXPn) wobei n = ar(Konstruktor).| (EXP EXP )| (caseTY P EXP (Pat1 → Exp1) . . . (Patn → Expn))Hierbei muss im case-Ausdruck n die Anzahl der Konstruktorenvon TYP sein und fur jeden Konstruktor von TYPmuss es genau ein Pattern geben.Das Konstrukt Pati → Expi heißt auch case-Alternative.

Pat ::= Konstruktor V1 . . . VnHier muss n die Stelligkeit des Konstruktors sein.Die Variablen Vi mussen alle verschieden sein.

Ein Programm besteht aus einer Liste von Superkombinatordefinitionen derForm s x1 . . . xn = e womit s die Stelligkeit n bekommt. Es gibt den ausge-zeichneten Superkombinator main, dessen Auswertung den Wert des Programmsergibt.

Beispiel 1.1.2 Fur Ausdrucke, Funktionen und Superkombinatoren:

Id := λx.x IdentitatK := λx.λy.x konstanter KombinatorD := λf.λx.f(x x)Y := λf.D f (D f) FixpunktkombinatorA := λz.λx.x (z z x)YTu := (A A) Turings Fixpunktkombinator

map f x := case x of Nil→ Nil; (y : ys)→ (f x) : (map f x ys)(++) xs ys := case xs of Nil→ ys; (z : zs)→ z : (zs ++ ys)

1.1.2 Auswertungsregeln, Normalordnungsreduktion

Definition 1.1.3 Ein Wert bzw. eine WHNF (weak head normal form, schwa-che Kopfnormalform) in KFPTS ist ein Ausdruck von der Form c t1 . . . tn,wobei c ein Konstruktor ist und n = ar(c), oder eine Abstraktion: λx . e, oderein Ausdruck (s t1 . . . tm), wobei s ein Superkombinator der Stelligkeit n > mist.Wir unterscheiden die Werte nach ihrer Struktur als

• FWHNF, wenn die WHNF eine Abstraktion ist, oder ein Ausdruck derForm (c s1 . . . sn), c ein Konstruktor und ar(c) > n, oder

• CWHNF ( constructor WHNF), wenn die WHNF ein Ausdruck der Form(c s1 . . . sn), c ein Konstruktor und ar(c) = n

Wir definieren Programmkontexte:

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 4

Definition 1.1.4 Ein Programmkontext (ein Kontext) ist ein Ausdruck, deran einer Stelle ein “Loch“ hat, an dem ein Ausdruck eingesetzt werden kann.Ein Kontext kann sein:

C ::= [] | (e C) | (C e) | (λx . C) |(c e1 . . . ei−1 C ei+1 . . . ear(c)) |caseT C (p1 → t1) . . . (pn → tn) |caseT t (p1 → t1) . . . (pi → C) . . . (pn → tn)

Beispiel 1.1.5 Damit sind als Kontexte z.B. definiert:

• [] : der leere Kontext. Setzt man einen Ausdruck e in den leeren Kontextein, so ergibt sich e selbst.

• (x (· y)). Einsetzen von e in den Kontext ergibt (x (e y))

• caseT (x ·) (p1 → t1) . . . (pn → tn). Einsetzen von e in den Kontextergibt caseT (x e) (p1 → t1) . . . (pn → tn)

Beachte, dass innerhalb eines Pattern kein Loch sein kann, ebenso ist der Kon-text λ · .e nicht moglich.Innerhalb von Kontexten erlauben wir das Einfangen von freien Variablen. D.h.es tritt der Effekt auf, dass die Namen von gebundenen Variablen eine Rollespielen, sofern das Loch innerhalb des Rumpfs einer Abstraktion ist. Z.B. istder Kontext λx . [] vom Kontext λu . [] verschieden, da beim Einsetzen von xjeweils andere Ausdrucke entstehen. Wir werden den Begriff der Gleichheit undUngleichheit von Ausdrucken noch formaler spezifizieren.

Definition 1.1.6 Auswertungsregeln (Reduktionsregeln):

Beta((λx.t) s)

t[s/x]

Case(caseT (c t1 . . . tn) . . . (c x1 . . . xn → s) . . .)

s[t1/x1, . . . , tn/xn]

SKBeta(k s1 . . . sn)

ek[s1/x1, . . . , sn/xn]Wenn der Superkombinator k die Stelligkeit n hat

Wir nennen das die unmittelbare Reduktion von Ausdrucken.Die Reduktionsregeln kann man in allen Programmkontexten verwendet. D.h.Wenn s → t in einem Schritt auswertet, dann gilt auch C[s] → C[t] fur jedenProgrammkontext C.Die Reduktionsrelation schreiben wir als s → t, wenn die Reduktion in ei-nem Schritt erfolgt. Die transitive bzw. reflexiv-transitive Hulle schreiben wir

als s+−→ t bzw. s

∗−→ t.Der Begriff des Redex (reducible expression) kann jetzt definiert werden: Wennin C[s] das s unmittelbar reduziert werden kann, dann ist s (zusammen mitseiner Position) ein Redex in C[s].

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 5

Fur die Normalordnungs-Reduktion (Normal-Ordnungs-Reduktion, Standard-Reduktion), braucht man Reduktionskontexte:

Definition 1.1.7 Reduktionskontexte sind:

R ::= [] | (R e) | caseT R (p1 → t1) . . . (pn → tn)

Das Loch eines Reduktionskontextes ist nicht unter einem Konstruktor oder imRumpf einer Abstraktion, ebenso nicht im Argument einer Anwendung.Die Normalordnungs-Reduktion ist diejenige, die immer in einem Reduktions-kontext den Ausdruck unmittelbar reduziert:

Definition 1.1.8 Sei R[s] ein Ausdruck, so dass R ein Reduktionskontext ist,wobei s keine WHNF ist, und s reduziert unmittelbar zu t:Dann ist R[s]→ R[t] die Normalordnungsreduktion (Standardreduktion, normalorder reduction) von R[s].Der Unterausdruck s zusammen mit seiner Position wird auch Normalordnungs-redex genannt. Die Reduktionsrelation wird mit der Markierung no versehen.Analog wie oben bezeichnen wir die transitive und reflexiv-transitive Hulle mitno,+−−−→ bzw.

no,∗−−−→.Wenn ein geschlossener Term t mittels Normalordnungsreduktionen zu einerWHNF reduziert, dann sagen wir, t terminiert (bzw. konvergiert) (englisch:terminates, converges) und bezeichnen dies mit t⇓. Andernfalls divergiert t,bezeichnet mit t⇑.

Manchmal sagen wir auch, t hat eine WHNF, wenn t zu einer WHNF re-duziert. Die WHNF, zu der t unter Normalordnung reduziert, ist eindeutig,aber es gibt i.a. viele WHNFs zu denen ein Term t (auch unter nicht-Normal-ordnungsreduktionen) reduzieren kann. Z.B. t ≡ (cons ((λx.x) True)) Nil) istselbst in WHNF, aber (cons True Nil) ist ebenfalls eine WHNF zu t.Damit haben wir alle zur Auswertung von Ausdrucken notwendigen Begriffedefiniert und konnen jetzt Ausdrucke auswerten.

Beispiel 1.1.9 ((λx.x) Nil)no−→ Nil

((λx.λy.x) s t)no−→ ((λy.s) t)

no−→ s.

Lemma 1.1.10 Es gilt:

• Jede unmittelbare Reduktion in einem Reduktionskontext ist eine Normal-ordnungsreduktion.

• Die Zerlegung eines Ausdrucks s in R[s′] kann auf mehrere Weisen moglichsein.

• Normalordnungsreduktion und der zugehorige Normalordnungsredex sindeindeutig in einem Ausdruck t, falls diese existieren.

• Eine WHNF hat keinen Normalordnungsredex und erlaubt keine Normal-ordnungsreduktion.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 6

Wir benutzen KFPT und KFPTS als Basis-Sprachen fur die weiteren Betrach-tungen, ebenso wie fur die folgende Striktheitsanalyse.

Bei KFPTS wird i.a. der Ausdruck zu main als der dynamische Ausdruck be-trachtet, und die anderen Definitionen als statisch, wahrend in KFPT dieseUnterscheidung nicht existiert. Wir werden sehen, dass es auch einen wichti-gen formalen Unterschied gibt zwischen dem main-Ausdruck und den anderenAusdrucken in KFPTS.

1.1.3 Eigenschaften der Normalordnungsreduktion

Wenn KFPTS gemeint ist, dann betrachten wir alles innerhalb des main-Ausdrucks und sehen die Superkombinator-Definitionen als global definiert an.

Definition 1.1.11 (Kontextuelle Aquivalenz in KFPT) Seien s, t zwei KFPT-Ausdrucke. Wir definieren

s ≤c t :⇐⇒ ∀C[] : C[s]⇓ ⇒ C[t]⇓

und sagen s approximiert t kontextuell.s ∼c t ist definiert als s ≤c t ∧ t ≤c s.

s ∼c t ⇐⇒ ∀C[] : C[s]⇓ ⇐⇒ C[t]⇓

Wir sagen dann: s, t, sind kontextuell aquivalent.

Wir geben eine Erweiterung an fur KFPTS, die auch zusatzliche Superkombi-natordefinitionen im Kontext erlaubt.Als Kontexte betrachten wie hier ein Paar (C,G) wobei C ein Ausdruckskontextunter Benutzung und G eine Menge von Superkombinatordefinitionen ist undC bereits welche daraus benutzen kann. (C,G)[s] ist dann das Programm mitSuperkombinatordefinition G und main-Ausdruck C[s]. Zusammensetzen von 2Kontexten (C1, G1) und (C2, G2) ist (C1C2, G1 ∪G2).

Definition 1.1.12 (Kontextuelle Aquivalenz in KFPTS) Seien s, t zweiKFPTS-Ausdrucke. Wir definieren

s ≤c t :⇐⇒ ∀(C,G) : (C,G)[s]⇓ ⇒ (C,G)[t]⇓

und sagen s approximiert t kontextuell.s ∼c t ist definiert als s ≤c t ∧ t ≤c s.

s ∼c t ⇐⇒ ∀C[] : C[s]⇓ ⇐⇒ C[t]⇓

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 7

Wir sagen dann: s, t, sind kontextuell aquivalent.

Ab hier betrachten wir wieder KFPT bzw. Unter-Ausdrucke von main bzgl.KFPTS unter globalen Superkombinatordefinitionen. In Analogie zu denChurch-Rosser-Satzen gelten Aussagen zur kontextuellen Aquivalenz. Daruberhinaus hat man auch noch Aussagen zur Reduktionslange. d.h zur Anzahl derNormalordnungs-Reduktionen, die benotigt werden um einen Ausdruck zurWHNF zu reduzieren (auszuwerten).

Definition 1.1.13 Eine Kongruenz auf KFPTS-Ausdrucken ist eine RelationR, die eine Aquivalenzrelation ist und fur die gilt: s R t =⇒ C[s] R C[t] furalle C.Eine Prakongruenz auf KFPTS-Ausdrucken ist eine Relation R, die einePraordnung ist (reflexiv und transitiv) und fur die gilt: s R t =⇒ C[s] R C[t]fur alle C.

Es gilt, dass ≤c eine Prakongruenz und dass ∼c eine Kongruenz ist. D.h.s ∼c t =⇒ C[s] ∼c C[t] fur alle s, t, C, und s ≤c t =⇒ C[s] ≤c C[t] fur alles, t, C.Außerdem ist ≤c eine Praordnung und ∼c eine Aquivalenzrelation.Wir benotigen einige Eigenschaften der Sprache KFPTS, die wir hier wiederho-len, bzw. ohne Beweis darstellen.

Satz 1.1.14 Sei t ein (evtl. offener) Ausdruck. Wenn t⇓, d.h. tno,∗−−−→ t1, t1 ist

eine WHNF, und t → t′ mit einer (auch nicht-Normalordnungs-) Reduktion.Dann gilt t′⇓.

t

no,∗��

// t′

no,∗�����

t1WNHF

∗ //___ t′1(WNHF)

Beweis. (siehe andere Skripte) 2

Die Diagrammnotation soll folgendes sagen: durchgezogenen Pfeile sind die vor-gegebenen und die gestrichelten Pfeile sind die Reduktionen die dann folgen(bzw. existieren).

Satz 1.1.15 (Standardisierung). Sei t ein (evtl. offener) Ausdruck. Wenn

t∗−→ t1 mit beliebigen (Beta), (SKBeta) und (case)-Reduktionen, wobei t1 eine

WHNF ist, dann existiert eine WHNF tNF , so dass tno,∗−−−→ tNF , und tNF

∗−→ t1.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 8

t

no,∗�����

&&LLLLLLLLLLLLL

t1,NF

(WNHF)∗ //___ t1

(WNHF)

Beweis. (siehe andere Skripte) 2

Satz 1.1.16 (Invarianz der Terminierung) Seien t, t′ (evtl. offene) Ausdruckemit t→ t′. Dann gilt t⇓ ⇐⇒ t′⇓

Beweis. Das folgt aus Satz 1.1.15 (Standardisierung) und Satz 1.1.14:Sei t→ t′ und t⇓. Dann folgt aus Satz 1.1.14, dass t′⇓.Sei t→ t′ und t′⇓. Dann ist t→ t′

∗−→ tWHNF und Satz 1.1.15 impliziert t⇓. 2

Korollar 1.1.17 Seien t, t′ (evtl. offene) Ausdrucke mit t→ t′.Dann gilt t ∼c t

Beweis. Sei C ein Kontext so dass C[t]⇓. Da C[t] → C[t′] gilt, folgt aus Satz1.1.16, dass auch C[t′]⇓. Die Umkehrung folgt genauso. 2

Die kontextuelle Approximation kann man erkennen, auch wenn man die Ein-schrankung macht, dass C]s], C[t] geschlossen ist,

Aussage 1.1.18 Seien s, t Ausdrucke: Dann gilt:

s ≤c t :⇐⇒ ∀C[] : Wenn C[s], C[t] geschlossen sind, dann C[s]⇓ ⇒ C[t]⇓

Beweis. Es ist klar, dass⇒ gilt. Um die andere Richtung zu zeigen, nehmen wirmal an, dass die rechte Bedingung gilt, und dass fur einen gegebenen KontextC die Relation C[s]⇓ gilt. Sei {x1, . . . , xn} die Menge der freien Variablen in

C[s], C[t]. Dann definiere C ′ := (λx1 . . . xn.C) ⊥ . . .⊥. Man sieht dass, C ′[s]∗−→

σ(r)⇓, wobei σ = {x1 7→ ⊥, . . . , xn 7→ ⊥} ist. Aus der Voraussetzung folgt,dass auch C ′[t]⇓ gilt. Genauso wie fur s sieht man mit vollstandiger Induktion,

dass C ′[t]∗−→ σ(u)⇓ gilt wobei C[t]

∗−→ u. Das kann aber nur sein, wenn u eineAbstraktion oder ein Konstruktorausdruck ist, und somit gilt auch C[t]⇓. 2

Folgende Aussage wird eine wichtige Rolle spielen beim Nachweis der Korrekt-heit der Striktheitsanalyse.In KFP, KFPT und KFPTS gilt folgendes:

Aussage 1.1.19 Sei t ein (evtl. offener) Ausdruck. Wenn tno,k−−−→ t1 wobei t1

eine WHNF ist und t′ ist ein Ausdruck mit t→ t′.Dann terminiert die no-Reduktion von t′ und es gibt eine WHNF t′1 so dass:

t′no,k′

−−−→ t′1, t1∗→ t′1 und k ≥ k′.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 9

t

kno

��

// t′

≤kno

��������

t1∗ //______ t′1

Beweis. Siehe andere Skripte. 2

Definition 1.1.20 Wir definieren fur jeden Term t mit t⇓ die Lange einer Nor-malordnungsreduktion zur WHNF als rln(t). Hierbei nehmen wir auch an, dassdas Resultat ∞ ist im Falle, dass t eine unendliche Normalordnungsreduktionhat oder die Reduktion auf einen Typfehler trifft. Falls t freie Variablen hat,und die Normalordnung mit einem Term der Form R[x] stoppt, dann ist rln(t)undefiniert.

Damit kann man Aussage 1.1.19 (fur die Sprachen KFP, KFPT und KFPTS)anders formulieren und etwas erweitern:

Aussage 1.1.21 Sei t ein (evtl. offener) Ausdruck, rln(t) sei definiert und

t∗→ t′.

Dann ist rln(t′) ≤ rln(t).

Nachteil der rln(t)-Definition ist, dass es zu weit weg ist von der wirklichen Im-plementierung: Call-by-name benutzt kein Sharing, sondern kopiert die Argu-mente und setzt diese in den Rumpf ein, so dass hier potentielle Vermehrfachungvon Redexen passieren kann.

Bemerkung 1.1.22 Nimmt man eine etwas andere Relation auf Ausdrucken,die statt Terminierung die Reduktion auf gleiche Werte betrachtet, dann erhaltman eine Relation die higher-order Funktionen zu stark unterscheidet.Sei ein Wert definiert als ein Ausdruck, der nur aus Konstruktoren und Ab-straktion besteht. Die Relation sei definiert:s ∼v t :⇐⇒ fur alle C, Werte v: C[s]⇓v ⇐⇒ C[t]⇓vEs gilt s ∼v t =⇒ s ∼c t.Die Umkehrung gilt nicht, da bei Abstraktionen als Werte verlangt wird, dassdiese (bis auf Umbenennung) gleich sind. Z.B. gilt λx.Nil ++ x ∼c λx.x (daserfordert einen Beweis, siehe andere Skripte), aber die Abstraktionen sind syn-taktisch verschieden.Außerdem wird die Auswertung in Haskell nur bis zur WHNF durchgefuhrt.

Die nachste Variante einer Gleichheitsrelation ware:s ∼′v t :⇐⇒ fur alle C, Boolesche Werte v: C[s]⇓v ⇐⇒ C[t]⇓v.Diese Relation ∼′v macht interessanter Weise λx.⊥ und ⊥ gleich, da λx.⊥ nichtals Wert zahlt, aber λx.⊥⇓ und ⊥⇑.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 10

1.2 Wiederholung: andere Sprachabstraktionen:Die ungetypte Kernsprache KFP

Zur Erinnerung hier nochmal die Definition der Sprache KFP, die eine sehreinfache Syntax und wenig Reduktionsregeln hat.

Syntax: Es gibt Konstantensymbole, die jeweils eine feste Stelligkeit haben.Diese nennen wir Konstruktoren. Die Anzahl der Konstruktoren sei N , die Kon-struktoren seien mit ci, i = 1, . . . , N bezeichnet.Wir nehmen an, dass es eine Moglichkeit gibt, alle Konstruktoren mit Stelligkeitanzugeben, ohne dass wir diese Methode naher spezifizieren. Zum Beispiel alseine Auflistung aller Konstruktoren mit Stelligkeit.

Definition 1.2.1 Eine einfache kontextfreie Grammatik fur KFP-Ausdrucke(Terme, Expressions EXP ) ist:

EXP ::= V V sind Variablen| λV . EXP wobei V eine Variable ist.| (EXP EXP )| (c EXP1 . . . EXPn) wobei n = ar(c)| (case EXP {Pat1 → Exp1; . . . ;PatN+1 → ExpN+1})

Hierbei ist Pati Pattern zum Konstruktor i, undPatN+1 das Pattern lambda.(Pati → Expi) heißt auch case-Alternative.

Pat ::= (c V1 . . . Var(c)) | lambdaDie Variablen Vi mussen alle verschieden sein.

Wesentlich ist die andere Struktur des jetzt ungetypten case-Konstruktes: Esgibt nur ein case, und es sind stets alle Konstruktoren als Alternativen vorhan-den, ebenso eine weitere Alternative, die mit dem Pattern lambda abgedecktwird, und die zum Zuge kommt, wenn der zu untersuchende Ausdruck eineAbstraktion ist.

1.3 Programmtransformationen und Optimie-rungen

Im folgenden verwenden wir KFPTS, da es naher an Haskell liegt, und beiAnalysebeispielen zT auch sinnvollere Angaben liefert. Z.B. kann man leichterAussagen uber ungetypte Argumenteinsetzungen u.a vermeiden.Man kann auch leichter mit rekursiven Funktionen umgehen. Die Ein-schrankung, die wir hinnehmen mussen, ist dass wir die Betrachtungen auf denmain-Ausdruck beschranken mussen, und die Superkombinatordefinitionen alsglobale Definitionen ansehen. Allgemeiner: man kann die Analysen und Ergeb-nisse immer dann anwenden, wenn man lokal nur Definitionen von Superkom-binatoren verwendet hat, die man als global ansehen kann.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 11

Definition 1.3.1 Korrekte Programmtransformationen sind binare RelationenP R P ′, die die Semantik der Programme nicht verandern, d.h. P R P ′ ⇒ P ∼c

P ′.

An leicht nachweisbaren korrekten Programmtransformationen hatten wir diepartielle Auswertung. D.h. s → t fur Unterausdrucke, und ebenso induktiv be-weisbare Gleichungen, die rekursive definierte Funktionen betrafen, wie z.B.foldr g e (xs++ys) ∼c foldr g (foldr g e ys) xs

foldl f e xs ∼c foldr (flip f) e (reverse xs)

xs++nil ∼c xs

xs++(ys++zs) ∼c (xs++ys)++zsDiese Gleichungen kann man einsetzen, um Programme zu transformieren undhoffentlich auch zu optimieren.

Ein Gegenbeispiel zu unbeschrankter Einsetzung, das als Warnung vor inkor-rekten Transformationen dienen kann, und zeigt, warum man sich in KFPTSerst mal nur auf den main-Ausdruck beschrankt, diskutieren wir hier ein Beispielvon David Sands:

Beispiel 1.3.2 Die Funktionen (Superkombinatoren) repeat und tail seiendefiniert durch

repeat x = x : repeat x

tail x = case x of (Nil -> bot) (y:ys -> ys)

Man kann nachweisen, dass fur alle Ausdrucke x die Gleichung

tail(repeat x) ∼ (repeat x)

gilt. Benutzt man diese Gleichung im Definitions-Rumpf der Funktion repeat,erhalt man die neue Funktion:

repeat’ x = x : tail(repeat’ x)

Leider hat diese Funktion andere Eigenschaften als repeat, z.B. kann manden tail von repeat′ x nicht mehr berechnen: tail (repeat’ a) →tail (a: tail(repeat’ a)) → tail(repeat’ a)), und die Reduktion ist ineiner Schleife.D.h. repeat und repeat’ sind nicht kontextuell aquivalent.Hier hat man in unzulassiger Weise die rekursive Definition einer Funktionverandert. (Die Ersetzung war ja nicht im main-Ausdruck)

Als praktischen Hinweis geben wir hier Bedingungen an, unter denen die Me-thode bei Anwesenheit von rekursiv definierten Superkombinatoren korrekt ist:

• Wenn die Ersetzung s = t an einer Position vorgenommen wurde, sodass die kontextuelle Gleichheit von s ∼c t ohne Bezugnahme auf die-se Position gezeigt werden kann. Genauer: es gibt ein Unterprogramm P ′,

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 12

(das abgeschlossen ist bzgl. aller Definitionen), so dass s ∼c t eine Glei-chung bzgl. des Unterprogramms P ′ ist. Dann kann man die Ersetzungin allen Ausdrucken machen, die außerhalb von P ′ sind. Z.B. kann mantail(repeat x) = (repeat x) an Stellen verwenden, die außerhalb derDefinitionen von tail und repeat liegen.

• Wenn die Ersetzung s→ t einerseits so ist, dass s ∼c t gilt, und anderer-seits die Anzahl der Normalordnungsreduktionen dadurch in keinem Termvergroßert wird (siehe unten im Abschnitt

”Verbesserungen“).

1.3.1 Verbesserungen (Improvements)

Dies ist adaptiert aus den Arbeiten von David Sands, (1994,1996,1999) undformalisiert den Zeitbedarf von Ausdrucken unter Benutzung der Anzahl vonNormalordnungs-Schritten. In den Papieren von D. Sands ist das Maß entwederdie Anzahl der Funktionsaufrufe oder die Anzahl der Schritte einer abstraktenMaschine (i.a. Mark-1 von Sestoft), so dass wir die Resultate dort nicht ganzdirekt ubernehmen konnen.Wir verwenden als Maß die Anzahl der Normalordnungsreduktionen. Dadurchkann man Methoden studieren, die nachweisen, dass die Ersetzung eines Aus-drucks s durch einen

”besseren“Ausdruck t in einem Programm stets eine Opti-

mierung bzgl. der Zeit darstellt. Wichtig ist, dass man den Begriff so formuliert,dass die Ersetzung immer weniger oder gleich viel Zeit benotigt, unabhangigdavon, wo man den Ausdruck in einem Programm durch einen anderen ersetzt.Leider sagt diese Verbesserungsbeziehung nichts uber den Platzbedarf aus.Ebenso muss man die ubliche Vorsicht walten lassen, wenn man die Anzahl derSchritte im formalen Modell ubertragen will auf die von einer Implementierungverbrauchte Zeit.Problematisch bei der Formalisierung ist, dass ein call-by-name Kalkul zugrundeliegt, der kein Sharing berucksichtigt. Deshalb sind die Ergebnisse (d.h. Aussa-gen zu Optimierungen) dieser Theorie in vielen Fallen nicht auf Haskell ubert-ragbar, da in Haskell Sharing berucksichtigt wird. Die Ergebnisse sind brauch-bar, wenn bei den Reduktionen keine Terme verdoppelt werden. Dies ist in denBeispielen unten der Fall.

Definition 1.3.3 Seien s, t zwei Ausdrucke mit s ∼c t. Wenn

∀C[] : rln(C[s]) ≤ rln(C[t])

dann schreiben wir s � t und sagen s ist optimaler als t.Wenn s � t und es einen Kontext C[] gibt mit rln(C[s]) < rln(C[t]), dannschreiben wir s ≺ t und sagen s ist echt optimaler als t.

Bei D. Sands heißt diese Beziehung strong improvement.Es gilt offenbar, dass � eine reflexive und transitive Relation ist (d.h. eine Pra-Ordnung).Weiter gilt: s � t⇒ C[s] � C[t].Eine einfache Optimierung ist die Ersetzung von s durch ein Redukt:

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 13

Satz 1.3.4 Sei s→ t fur zwei (auch offene) KFPT-Ausdrucke. Dann gilt t � s,d.h. t ist eine Verbesserung von s.

Beweis. Sei C ein Kontext und s→ t. Dann gilt auch C[s]→ C[t], da Reduktio-nen uberall erlaubt sind. Nach Aussage 1.1.21 gilt C[s] ∼c C[t]. Nach Aussage1.1.19 gilt rln(C[s]) ≥ rln(C[t]). Da das fur alle Kontexte gilt, gilt auch t � s.2

Es gilt der folgende Satz: (Improvement Theorem von David Sands:)

Satz 1.3.5 Wenn in einer rekursiven Definition von Superkombinatoren eineErsetzung t durch s durchgefuhrt wurde, und vor der Ersetzung galt s � t,dann sind alle Ausdrucke r vor und nach der Ersetzung semantisch gleichwertig(kontextuell aquivalent). D.h. Terminierung bleibt erhalten.

Dadurch kann man nicht nur in KFPT an von Definitionen unabhangigenStellen optimieren mittels �, sondern auch innerhalb von Definitionen.

Ein Multikontext C[., . . . , .] ist ein Ausdruck mit n Lochern, wobei jedes Lochgenau einmal vorkommen muss. Genauer: Seien []i die Bezeichnung fur Loch i.Dann ist ein Ausdruck C[[]1, . . . , []n] (der erzeugt wird wie ein Ausdruck, aber []iist ebenfalls erlaubt als Unterausdruck) ein Multi-kontext mit den n Lochern,wenn jedes Loch []i genau einmal vorkommt. Der Ausdruck C[t1, . . . , tn] be-zeichnet die Einsetzung der Ausdrucke in die Locher, ohne Umbenennung vonVariablen: C[t1, . . . , tn] = C[[]1, . . . , []n][t1/[]1, . . . , tn/[]n].

Aussage 1.3.6 Wenn si � ti fur i = 1, . . . , n, dann gilt auch C[s1, . . . , sn] �C[t1, . . . , tn] fur einen Multikontext C[., . . . , .].

Beweis. Mit Induktion nach i. Es gilt: C[s1, s2, . . . , sn] � C[t1, s2, . . . , sn] �. . . � C[t1, t2, . . . , tn−1, sn] � C[t1, t2, . . . , tn−1, tn]. Daraus folgt die Behaup-tung, da � transitiv ist. 2

Korollar 1.3.7 Wenn si � ti, fur i = 1, . . . , n, dann gilt c s1 . . . sn � c t1 . . . tnfur einen Konstruktor c der Stelligkeit n.

1.3.2 Eine Methode zum Nachweis von �Wir geben eine Moglichkeit an, s � t zu zeigen. Dies ist in Analogie zum Induk-tionsschema zum Nachweis der kontextuellen Aquivalenz.

Definition 1.3.8 Zunachst definieren wir die Menge List der geschlossenenListenausdrucke als den großten Fixpunkt der Bedingung:s ∈ List wenn s geschlossen und:

• s ∼c ⊥ oder

• s ∼c Nil oder

• s ∼c s1 : s2 und s2 ∈ List. 2

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 14

Beachte: s ∼c s1 : s2 ∧ s2 ∈ List ist gleichwertig zu: sno,∗−−−→ t1 : t2 ∧ t2 ∈ List .

Um das Verfahren der Bildung eines großten Fixpunkts nochmals zu illustrieren,definieren wir den Operator Φ auf Mengen von KFPT-Ausdrucken:Φ(L) := {s | s ∼c ⊥ oder s ∼c Nil oder s ∼c s1 : s2 und s2 ∈ L}List ist dann der großte Fixpunkt von Φ auf der Menge der KFPT-Ausdruckeund kann erhalten werden als der unendliche Schnitt uber die MengenΦi(LKFPT ). Der Nachweis, dass ein Ausdruck s in List ist, kann mit Induktionfolgendermaßen gefuhrt werden: Wenn es fur jede Listentiefe n nicht moglichist, das Enthaltensein zu widerlegen, dann ist s ∈ List .

Beispiel 1.3.9 Fur alle xs, ys ∈ List gilt, dass xs ++ ys ∈ List: Die Induktiongeht nach Listentiefe n und Fallunterscheidung nach der Variablen xs.Wenn xs ∼c ⊥, dann ist auch xs ++ ys ∼c ⊥.Wenn xs ∼c Nil, dann ist xs ++ ys ∼c ys, und ys ist bereits in List. Daserfullt die Bedingung.Wenn xs ∼c x

′ : xs′, wobei xs′ ∈ List, dann ergibt die Reduktion von (x′ :xs′) ++ ys ∼c x

′ : (xs′ ++ ys), und Induktion nach der Tiefe kann verwendetwerden.

Der nachste Schritt um � auf Listen zu verstehen, ist folgende Definition:

Definition 1.3.10 Die Menge ImpListPaar von geschlossenen Ausdrucken istder großte Fixpunkt der Bedingung: Fur ein Paar (s, t) ∈ ImpListPaar sollgelten:

• s ∼c ⊥, und t ∼c ⊥; oder

• s no,k−−−→ Nil, tno,k′

−−−→ Nil und k ≤ k′; oder

• s no,k−−−→ s1 : s2, tno,k′

−−−→ t1 : t2, k ≤ k′, s1 � t1, und (s2, t2) ∈ ImpListPaar.2

Dies ist eine Menge von Paaren von geschlossenen Listenausdrucken (s, t), sodass s optimaler als t ist, aber zunachst im leeren Kontext.Wir benutzen im folgenden die Tatsache (ohne Beweis), dass aus (s, t) ∈ImpListPaar auch s ∼c t folgt.

Aussage 1.3.11 Wenn (s, t) ∈ ImpListPaar, dann gilt s � t.

Beweis. Wir zeigen dass fur einen beliebigen Multikontext C[., . . . , .] und Paare(si, ti) mit (si, ti) ∈ ImpListPaar oder si � ti die Aussage rln(C[s1, . . . , sn]) ≤rln(C[t1, . . . , tn]) gilt:Wenn rln(C[s1, . . . , sn]) undefiniert ist oder rln(C[s1, . . . , sn]) =∞, dann auchrln(C[t1, . . . , tn]) undefiniert oder rln(C[t1, . . . , tn]) = ∞, da C[s1, . . . , sn] ∼c

C[t1, . . . , tn]).In den anderen Fallen zeigen wir die Behauptung mit Induktion nach der An-zahl der Normalordnungsschritte von C[s1, . . . , sn], zweitens nach der Anzahl

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 15

der Locher von C, drittens nach der Anzahl der Normalordnungsschritte vonC[t1, . . . , tn] (falls notig).Wenn es keinen Normalordnungsredex mehr gibt, dann ist C[s1, . . . , sn] eineWHNF und es gilt die Behauptung.Wenn es einen Normalordnungsredex in C[s1, . . . , sn] gibt, muss man Falle un-terscheiden:

1. Der Normalordnungsredex ist ganz in C[. . .]. Dann hat man nach einerNormalordnungsreduktion von C[s1, . . . , sn] und von C[t1, . . . , tn] eine Si-tuation, auf die man Induktion anwenden kann. Hier ist zu beachten, dassdie si, ti alle geschlossen sind, und evtl. kopiert werden.

2. Ein sj ist im Reduktionskontext. Es gilt nach Voraussetzung sj � tj .Dann konnen wir annehmen, dass das Loch j in einem Reduktions-kontext in C ist, unabhangig von den anderen Argumenten im Mul-tikontext. Dann ist tj ebenfalls im Reduktionskontext. Man kann dieInduktionshypothese anwenden auf C[s1, . . . , sj−1, sj , sj+1, . . . , sn] undC[t1, . . . , tj−1, sj , tj+1, . . . , tn], da die Reduktionslange gleich ist undman einen Kontext C ′ := C[·, . . . , ·, sj , ·, . . . , ·] mit einem Loch weni-ger als C hat. Wegen sj � tj gilt C[t1, . . . , tj−1, sj , tj+1, . . . , tn] �C[t1, . . . , tj−1, tj , tj+1, . . . , tn], und man kann die Induktionsbehauptungbeweisen.

3. Der Normalordnungsredex in C[s1, . . . , sn] ist von der Form (sj r), und sjist in WHNF. Dann kann der Fall (sj , tj) ∈ ImpListPaar nicht auftreten,da sj ja in List ist und dies einen dynamischen Typfehler darstellt, undsomit wie ⊥ behandelt wird. Wg. Voraussetzung gilt dann auch, dasstj r

′ ∼ ⊥.

4. Der Normalordnungsredex in C[s1, . . . , sn] ist von der Form case sj of altsund sj ist in WHNF. Beachte dass der case-Ausdruck zu C gehort, aberevtl nicht alle Unterausdrucke. Auch hier kann sj nur einen Listenkon-struktor als Topkonstruktor haben. Wenn tj nicht in WHNF ist, dannkann man einen Normalordnungsschritt durchfuhren, und dann Induk-tion anwenden. Wenn tj in WHNF ist, dann hat der Normalordnungs-redex von C[t1, . . . , tn] ebenfalls die Form case tj of alts. In diesemFall muss sj = sj1 : sj2 und tj = tj1 : tj2 sein mit sj1 � tj1 und(sj2, tj2) ∈ ImpListPaar sein. Nach der Ausfuhrung einer case-Reduktionauf beiden Seiten kann man wieder Induktion anwenden. Beachte, dassalle si, ti geschlossen sind und somit keine si in ein sj eingesetzt werden.

5. Wenn der Normalordnungsredex in C[s1, . . . , sn] von der Form case (u1 :su2) of alts ist, wobei u1, u2 evtl. ein si enthalt, dann ist das bereitsabgedeckt. Auch die Einsetzung kann die si nicht verandern, da diesegeschlossen sind. 2

Was jetzt noch fehlt, ist ein einfaches Rezept zum Nachweis von (s, t) ∈ImpListPaar . Wir bezeichnen in der folgenden Aussage einen Ausdruck s mits[x], wenn wir andeuten wollen, dass er die Variable x (evtl. mehrfach) enthalt.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 16

Aussage 1.3.12 Induktionsschema zum Nachweis folgender Aussage:Fur alle Listenausdrucke x ∈ List gilt: s[x] � t[x].Voraussetzung ist, dass schon nachgewiesen wurde, dass fur alle Listen x ∈ List:s[x] ∼c t[x] gilt.Angenommen, wir konnen fur jede der Einsetzungena ∈ List} (d.h. a ∼c ⊥, oder a ∼c Nil, oder a ∼c y : ys mit ys ∈ List}) zeigen,dass eine der folgenden Aussagen gilt:

• s[a] ∼c ⊥ ∼c t[a].

• s[a]no,k−−−→ r, t[a]

no,k′

−−−→ r wobei k ≤ k′ und r ∈ List.

• s[a]no,k−−−→ r1 : s[r2], t[a]

no,k′

−−−→ r1 : t[r2] wobei k ≤ k′ und r2 ∈ List.

• s[a]no,k−−−→ r1 : s[r2], t[a]

no,k′

−−−→ r3 : t[r2] wobei k ≤ k′, r2 ∈ List, und

r3∗−→ r1.

• s[a]no,k−−−→ r1 : s[r2], t[a]

no,k′

−−−→ r3 : t[r2] wobei k ≤ k′, r2 ∈ List, undr1 � r3.

Dann gilt fur alle Listenausdrucke r ∈ List: s[r] � t[r].Es gilt dann auch s[x] � t[x], wobei x hier eine Variable ist.

Dieses Induktionsschema kann erweitert werden auf andere rekursive Daten-strukturen wie Baume. Ebenso kann man das Induktionsschema ausdehnen aufGleichungen mit mehreren Variablen.Das Induktionsschema kann verbessert werden durch Betrachtung von nurWHNFs, wenn im Ausdruck s[x] die Variable x nur einmal vorkommt.

Bemerkung 1.3.13 Man kann das gleiche Schema auch auf fur den DatentypBool anpassen: Wenn man zeigen will, dass s[x] � t[x] ist, wobei x nur geschlos-sene Boolesche Ausdrucke sein durfen, dann ist es ausreichend zu zeigen:

1. s[x] ∼c t[x]

2. s[⊥]⇑ ⇐⇒ t[⊥]⇑.

3. Fur alle a mit a ∼c True: s[True]k−→ r1 =⇒ t[True]

k′

−→ r2 mit k ≤ k′

und r1 � r2 (oder r1 = r2).

4. Fur alle a mit a ∼c False: s[False]k−→ r1 =⇒ t[False]

k′

−→ r2 mit k ≤ k′und r1 � r2 (oder r1 = r2).

Zum Beispiel kann man dann zeigen, das not(not x) � x wenn nur BoolescheAusdrucke fur x erlaubt sind.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 17

Beachte, dass a ∼c True impliziert, dass a∗−→ True; ebenso fur False.

Man kann in KFPT, das es call-by-name ist, das Induktionsschema nicht nurauf ⊥, Nil, y : ys anwenden, da dann die Reduktion zu WHNF fehlt. Als Bei-spiel betrachte Ausdrucke uber Zahlen: x + x und 2 ∗ x + 0 kann mit einemInduktionsschema, das nur die Zahlen nimmt, als x+ x � 2 ∗ x+ 0 nachweisen,wobei man Addition und Multiplikation als 1 Schritt zahlt. Aber wenn manx = (1 + 1 + 1) nimmt, dann sieht man, dass das falsch ist.Was aber gilt, ist 2 ∗ x � x+ x.Diese leichten Merkwurdigkeiten werden besser, wenn man eine call-by-need(oder eine call-by-value) Sprache betrachtet.

Beispiel 1.3.14 Wir zeigen, dass fur alle Listen xs, ys, zs gilt:

xs ++ (ys ++ zs) � (xs ++ ys) ++ zs

1. ⊥: Sowohl ⊥ ++ (ys ++ zs) als auch (⊥ ++ ys) ++ zs haben keineWHNF. Somit ∞ ≤∞.

2. Nil: Nil ++ (ys ++ zs)no−→ case Nil . . .

no−→ (ys ++ zs)no−→

case ys (Nil→ zs) (u : us→ u : (us ++ zs)).

(Nil ++ys) ++ zsno−→ case (Nil ++ ys) (u : us → u : (us ++ zs))

no−→ case (case Nil . . .) . . .no−→ case ys (Nil → zs) (u : us → u :

(us ++ zs)). Das sind jeweils 3 Normalordnungsreduktionen auf jederSeite. Jetzt fehlt noch der Nachweis, dass xs ++ ys ∈ List. Das wurde inBeispiel 1.3.9 behandelt.

3. xs′ = x : xs: Wir betrachten die Normalordnungsreduktion der linken undrechten Seite:

((x : xs)++ ys) ++ zsno−→ case ((x : xs) ++ ys) of (Nil→ . . .) (u : us→ u : (us ++ zs))no−→ case (case (x : xs) . . .) of (Nil→ . . .) (u : us→ u : (us ++ zs))no−→ case (x : (xs ++ ys)) of (Nil→ . . .) (u : us→ u : (us ++ zs))no−→ x : ((xs ++ ys) ++ zs)Die andere Reduktion ergibt:

(x : xs)++ (ys ++ zs)no−→ case (x : xs) of (Nil→ . . .)(u : us→ u : (us ++ (ys ++ zs)))no−→ x : (xs++ (ys ++ zs))

Die erste Reduktion benotigt 4 Normalordnungs-Schritte, die zweite Re-duktion benotigt nur 2 Reduktionen. Danach kann man Induktion (nachder Tiefe) auf die Ausdrucke ((xs ++ ys) ++ zs) und (xs++ (ys ++ zs))anwenden.

Also kann man jetzt mit dem Induktionsschema schließen, dass fur alle Listenxs, ys, zs gilt:xs ++ (ys ++ zs) � (xs ++ ys) ++ zs.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 18

Beachte, dass hier nicht der allgemeine Nachweis gefuhrt wurde, dass jeder Aus-druck der Form ((s1 ++ s2) ++ s3) durch den Ausdruck (s1 ++ (s2 ++ s3))verbessert wird, da noch freie Variable vorkommen konnten.Das kann man aber ebenfalls allgemein nachweisen.

Beispiel 1.3.15 Wir wenden Aussage 1.3.12 versuchsweise auf die vermute-te Optimierung map (f . g) xs � map f (map g xs) bzw deren Umkehrungmap f (map g xs) � map (f . g) xs an.Zuerst probieren wir:map (f . g) xs � map f (map g xs)

Die Schritte sind:

map (f . g) (a:as) -> case a:as ...

-> (f.g) (a) : map (f . g) (as)

Das ist eine WHNF. Diese vergleicht man mit:

map f (map g a:as) -> map f (case a:as ... )

-> map f (g a : map g as) -> case (g a: map g as) ..

-> f (g a) : map f (map g as)

Analog zu applikativen Simulationen (Bisimulationen) kann man jetzt in derWHNF weiter reduzieren. Fur das erste Element berechnet man: (f.g) (a)

→ f (g a). Die Tails passen zum Induktionsschema. Man sieht, dass die ersteVariante bis zur WHNF weniger Reduktionsschritte benotigt, aber fur die Li-stenelemente einen Schritt mehr. Also kann man die Improvement-Beziehungnicht folgern.Es reicht auch nicht, die Summen der Reduktionsschritte zu vergleichen, wobeider erste Ausdruck immer noch besser abschneiden wurde: Man kann Kontex-te fur dieses Beispiel angeben, in denen die Improvementbeziehung falsch wird:Im Kontext (λx.C[x, . . . , x]) (hd ·) ist der Aufwand fur die Auswertung von(f.g) (a) zu (f (g a)) evtl. mehrfach erforderlich.Die andere Richtung ist leicht als falsch einzusehen.

Wenn man Sharing direkt (d.h. per Pointer oder Markierungen) verwendet,dann beobachtet man, dass map (f . g) xs gegenuber map f (map g xs) inallen einfachen Fallen eine Verbesserung ist. Allerdings ist das naive Sharingnicht ausreichend, da das Skoping berucksichtigt werden muss, denn solche ge-meinsam referenzierten Ausdrucke konnen ja kopiert werden.Das Beispiel zeigt damit, dass man zur vernunftigen Optimierung mittels Impro-vements das Sharing berucksichtigen muss, d.h. dass man eine Sprache benotigt,die das Sharing in der implementierten Auswertung (lazy evaluation) richtig mo-delliert. Genauer: man braucht ein let bzw. ein letrec in einem (erweiterten)Lambdakalkul. In den Kalkulen mit let bzw. letrec hat man aber komplexe-re Reduktionen, und man muss das Maß etwas verandern: die reinen “let”-Reduktionen darf man bei Betrachtungen zu Verbesserungen nicht mitzahlen.Aber: ob die entsprechende Improvement-Simulation bzw das Induktionsschemaauch in einem Sharing Kalkul die Improvement Relation nachweist ist ebenfallsnicht bewiesen.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 19

Es gibt Artikel zu Improvement: [San98]: ein call-by-name Kalkul ohne Sharing.[MS99] beschreibt einen call-by-need Kalkul mit Sharing, mit vielen Nachwei-sen und Optimierungsrelationen; Es ist ein Kernsprachenkalkul, der genau dieSchritte einer passenden abstrakten Maschine zahlt. Sands stimmt hier zu, dassdieses Maß zu fein ist und man auch ein groberes nehmen sollte, (z.B nur be-ta und case). Eine Beweismethode analog zur Simulation kann hilfreich sein,ebenso eine Erweiterung auf typisierte Kalkule.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 20

1.4 Striktheitsanalyse (mit abstrakter Redukti-on)

(Erik Nocker: fur Clean [Noc90] Marko Schutz fur Kernsprache [Sch00], Sabel,Schutz und Schmidt-Schauß [SSSS08].

Motivation

Informell ist eine Funktion f strikt in ihrem i-ten Argument, wenn sie diesesArgument auf jeden Fall auswertet, um einen Wert zuruckzugeben. Zum Beispielist K mit K x y = x strikt im ersten Argument, aber nicht strikt im zweitenArgument. Wenn alle Funktionen ihre Argument ohnehin auswerten, wie z.B.in ML, dann braucht man keine Striktheitsanalyse.In Haskell stellt die Striktheitsanalyse Informationen bereit, die bei der Kompi-lation aus den Funktionsdefinitionen (bzw. Spezifikationen) sequentielle interneFunktionen macht.In einer Tabelle sind hier schlagwortigartig (und auch leicht vereinfacht) dieEigenschaften nicht-strikter und strikter (funktionaler) Programmier-Sprachenin Bezug auf Optimierung und Striktheit zusammengestellt:

Nicht-strikte mit Sharing Strikte

Auswertung Normalordnung Anwendungsordnung

Reihenfolge Bestimmt durch Rumpf, undzur Laufzeit durch Auswer-tungsanforderung.Programmablauf nicht amFunktionscode erkennbar

Komplett bestimmt durch denRumpfProgrammablauf am Funktions-code erkennbar

Spezifikation WAS WIE

Information Intention bzw. Idee noch sicht-bar

Idee oft durch die Sequentiali-sierung verdeckt

Transforma-tionen

Viele Wenige, da Auswertungs-Reihenfolge eingehalten werdenmuss

Parallelisierung orientiert am Rumpf von Funk-tionen; automatische konserva-tive Parallelisierung; Semantikkann erhalten bleiben

orientiert am Rumpf von Funk-tionen; Parallelisierung mussReihenfolge einhalten; Paralleli-sierung fast nur durch Umpro-grammierung moglich

Es gibt verschiedene Grunde, siehe auch Tabelle oben, die eine Striktheitsanalysesinnvoll machen.

1. Striktheitsanalyse liefert Informationen, die eine Auswertungsumstellungerlauben, und damit eine Optimierung ermoglichen, ohne dass die Seman-tik verandert wird.

2. konservative und automatische Parallelisierung der Auswertungbenotigt Striktheitsinformation, wenn die Semantik nicht verandert wer-

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 21

den soll. Die Striktheitsanalyse liefert die Information, welche Ausdruckeman schon vorher auswerten kann, da sie spater auf jeden Fall benotigtwerden. Damit kann man spekulative Auswertung vermeiden, d.h. nurwirklich erforderliche Ausdrucke auswerten. Z.B muss man im Ausdrucks+ t, falls der Wert benotigt wird, s und t auswerten, bevor ein Ergebnisberechnet werden kann. Damit kann man s, t auch parallel auswerten. DerVorteil der referentiellen Transparenz ist hier, dass die s, t-Auswertungensich nicht gegenseitig beeinflussen (bis auf Datenabhangigkeit).

3. die Compilierung in eine abstrakte Maschine, G-Maschine oder STG-Maschine ergibt effizienteren Kode, wenn Striktheitsinformation vorliegt.Allerdings haben die Compilierungstemplates oft schon eine schwacheForm der Ausnutzung von Striktheitsinformationen eingebaut.

4. Es gibt (high-level) Transformationen, die als Vorbedingung Striktheits-informationen benotigen. Allerdings gibt es da auch andere interessanteVorbedingungen, z.B. Terminierung

In der einfachsten Variante einer abstrakten Maschine wird eine Funktion mitDefinition f x1 . . . xn = e so kompiliert, dass ein Knoten mit der Markierung(f t1 . . . tn) reduziert werden kann, d.h. durch den Graphen fur e ersetzt werdenkann, wobei die Variablenbindungen richtig verwaltet werden mussen.Der G-Maschinenkode macht in etwa folgendes:

• Aufbau eines Teilgraphen fur e unter Benutzung der Knoten fur t1 . . . tn

• Uberschreiben des Knotens (f t1 . . . tn) mit der Wurzel des neuen Teilgra-phen.

Wenn bekannt ist, dass eine Funktion f mit n Argumenten bestimmte Ar-gumente auf jeden Fall auswerten muss, dann kann man f deterministischerkompilieren: Wenn f strikt im i-ten Argument ist, dann kann man Auswertun-gen umstellen.

1.4.1 Striktheit

Definition 1.4.1 Die Funktion f nennt man strikt im i-ten Argument, wennf t1 . . . ti−1 ⊥ ti+1 . . . tn = ⊥ ist fur alle Ausdrucke tj, wobei ⊥ fur Terme ohneWHNF steht.

Beachte, dass diese Definition etwas allgemeiner ist als”f benotigt im-

mer das i-te Argument“, da diese Bedingung auch dann erfullt ist, wennf t1 . . . ti−1 ⊥ ti+1 . . . tn nicht terminiert ohne ti auszuwerten. Die Funktionλx.⊥ ist z.B strikt in ihrem Argument, da sie nie terminiert wenn sie auf einArgument angewendet wird, aber das Argument wird nicht ausgewertet!

Wenn f strikt im Argument xi ist, dann ist folgende Auswertungsumstellungmoglich:

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 22

f x1 . . . xi . . . xn wird kompiliert, so dass folgendes bei Auswertung von(f t1 . . . tn) passiert:

1. ti auswerten zu einer WHNF t′i

2. Aufbau des Graphen wie oben mit (f t1 . . . t′i . . . tn)

Definition 1.4.2 Ein Ausdruck s mit Unterausdruck t an der Stelle p, (fallsp nicht innerhalb einer Abstraktion oder in der Alternative eines case ist), iststrikt in t (an der Stelle p), wenn s[p 7→ ⊥] ∼c ⊥ gilt.

Das ist das gleiche wie zu definieren: λx.t[p 7→ x] ist strikt.

1.4.2 Vor- und Nachteile der Auswertungsumstellung

Vorteile der Vorauswertung von ti bei Kompilierung einer Funktion f , die striktim i-ten Argument ist gegenuber vorher (bzgl. der Zeit):

1. Der Zwischencode (G-Maschinenkode bzw. STG-Maschinenkode) fur fkann dann davon ausgehen, dass t′i in WHNF ist, und kann dadurch Ab-fragen sparen, insbesondere die Abfrage, ob ti bereits ausgewertet ist.

Betrachte beispielsweise die Funktion quadrat x = x*x. Diese wird naivkompiliert als:

... Push x, Push x, Pushglobal *, Mkap, Mkap, Update, ...

Dies bewirkt den Aufbau eines Knotens, der sofort wieder ausgewertetwird. Da ∗ strikt in seinen Argumenten ist, weiß man, dass die Auswertungvon t ∗ t auf jeden Fall die Auswertung von t erfordert. Also kann man tvorher auswerten. Dies ergibt:

... Push x, Eval, Push x, Mul, Update, ...

2. Wenn strikte Argumente von einem Typ sind, dessen Objekte sich in einem(Halb-) Wort darstellen lasst, dann kann man diese direkt darstellen, nichtnur uber eine Indirektion. Das ist die Unboxing-Optimierung

3. Programmtransformationen und Optimierungen in der STG-Maschinebenotigen teilweise, dass Ausdrucke strikt in einem Unterausdruck sind.Diese Optimierungen sind nach Erkennung der Striktheit erlaubt. DieseErkennung kann man mit Striktheitsanalyse durchfuhren.In der STG-Maschine kann man Update-Operationen im Heap einsparen,wenn man die Auswertung umgestellt hat, da man zT die Auswertung nurunter Benutzung des Stacks ausfuhren kann.

In vielen Fallen wird auch weniger Speicher von den so veranderten Funktionenbenotigt: D.h. weniger Speicher-Anforderungen und -Freigaben.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 23

Bemerkung 1.4.3 Es ist klar, dass man algorithmisch nicht jede Striktheits-information entdecken kann, da dies bedeuten wurde, dass man Terminierungentscheiden konnte. Denn: Striktheit ist unentscheidbar. Die Analysen werdenalso nur Approximationen berechnen konnen.

Wenn man “tiefe Striktheit“ verwenden will, dann wird leider in einigen Fallen(nach Striktheits-Optimierung) der Speicherverbrauch linear in der Eingabe,obwohl er vorher konstant war. Dies passiert beispielsweise bei Funktionen, dieeine Liste erzeugen, die summiert wird. Die Veranderung kann bewirken, dassvor Anwenden der Addition die ganze Liste erst aufgebaut wird, und dann erstverarbeitet, wahrend dies vorher nicht der Fall war.Im Beispiel sum [1..1000], wenn die Summation folgendermaßen definiert wur-de:

sum xs = foldl’ (+) 0 xs

foldl’ op e xs = case_lst xs of (nil -> e)

(u:us) -> strict (foldl’ op) (op e u) us

werden bei lazy Auswertung die Elemente der Liste in dem Moment erzeugt, indem die Addition sie braucht, d.h. konstanter Platzbedarf. Offenbar werden alleListenelemente ausgewertet. Nach einer “tiefen Striktheits“-Veranderung konn-te es hier passieren, dass zunachst die Liste bereitgestellt wird, und dann erstsummiert wird. Das ist offenbar eine nachteilige Veranderung der Auswertungs-reihenfolge.Man kann mit der Formalisierung der Verbesserungen (Improvements bzgl. An-zahl Reduktionen) – mit und ohne Sharing – formal nicht nachweisen, dassdie Striktheitsoptimierung wirklich eine Optimierung darstellt, da Striktheits-optimierung zwar die Reihenfolge der Reduktionen, nicht aber die Anzahl derReduktionen verandert.Man muss unterscheiden zwischen der KFPT-Reduktion die Argumente manch-mal verdoppelt, und der Reduktion mit Sharing. d.h.der lazy Auswertung.Zum Beispiel fur doppelt x = x+x wird die Reduktion von doppelt (1+1)

durch Striktheitsoptimierung verbessert.vorher: doppelt (1+1) → (1+1)+(1+1) → 2+(1+1) → 2+2 → 4nachher: doppelt (1+1) → doppelt 2 → 2+2 → 4Allerdings nutzt die Implementierung der lazy Reduktion ohnehin Sharing, sodass sich hierdurch keine Verbesserung ergibt. Die einzige Optimierung durchdie Reduktion vor Einsetzen in die Funktion entsteht durch Ausnutzen des Wis-sens, dass bestimmte Unterausdrucke in WHNF vorliegen. Die Ersparnis durchUmstellung besteht in einer Verminderung der

”Update“-Operationen der ab-

strakten Maschine. Die Ersparnis kann, je nach abstrakter Maschine, auch darinliegen, dass Abfragen ob etwas bereits ausgewertet ist, wegfallen kann.Es gilt z.B in einem Lambda-Kalkul mit letrec, dass t in Normalordnung genausoviele case- und lazy-Beta-Reduktionen bis zu WHNF benotigt, wie unter einerStrategie, die Umstellung der Auswertung aufgrund von Striktheit erlaubt.Einen Kalkul, der auch diese Reduktionsanzahl bei lazy Auswertung richtigsimuliert, werden wir evtl. noch behandeln.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 24

1.4.3 Abstrakte Reduktion

Die Idee der Striktheitsanalyse mittels abstrakter Reduktion ist ein symboli-scher Test auf Nichtterminierung:Betrachte abstrakte Ausdrucke (f > . . .> ⊥ > . . .>), unter Benutzung abstrak-ter Werte ⊥,>, wobei ⊥ fur einen Term ohne WHNF steht, und > fur beliebigeTerme. Dann reduziere den abstrakten Ausdruck, evtl. auch mit Fallunterschei-dung, bis sich nachweisen lasst, dass die Reduktion ⊥ ergibt. Fur diesen Nach-weis gibt es im wesentlichen die Kriterien:

1. ⊥ ist das Ergebnis der Reduktion, oder einer Alternative, die dann nichtmehr betrachtet werden muss.

2. Das Resultat ist ein ungetypter Ausdruck. (das kommt nicht vor bei einergetypten Striktheitsanalyse)

3. die abstrakte Reduktion lauft in eine Schleife.

Die Reduktion muss teilweise eine Fallunterscheidung machen, falls der Wertvon > benotigt wird.

Regeln fur die abstrakte Reduktion :

1. man darf reduzieren. Die erlaubten Reduktionsregeln sind wie in KFPTmit Kombinatoren: β-Reduktion, δ-Reduktion (d.h. Kombinatoreinset-zung), und case-Reduktion.

2. casetyp ⊥ alts→ ⊥

3. (⊥ e)→ ⊥

4. g . . .⊥ . . .→ ⊥, falls g strikt im entsprechenden Argument ist.

5. casetyp > . . . . . .→ ?In diesem Fall mussen alle Alternativen betrachtet werden. Es wird bei derUntersuchung des jeweiligen Falls > fur die Patternvariablen eingesetzt.

Fur den Gesamtausdruck muss nachweisbar sein, dass er ⊥ ergibt; d.h.jeder Fall ist zu betrachten.Hier ist der ungetypte Kalkul etwas problematisch, man muss eigentlichmehr Falle betrachten, kann sich aber auf getypte beschranken, wenn mannur getypte Verwendungen betrachten will.

Unklare Falle bzw. keine abstrakte Reduktion ist mehr moglich: Wenn der Nor-malordnungsredex von der Form ist:

1. (> t) Fallunterscheidungen mussten alle Abstraktionen abdecken?

2. Normalordnungsredex ist WHNF: Stopp, und Striktheit ist nicht erfullt.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 25

Beispiel 1.4.4length lst s = case_lst lst of nil -> s; x:xs -> length xs (s+1)

Wir argumentieren mal intuitiv, dass length strikt in beiden Argumenten ist,und versuchen eine einfache Reduktionsmethode:

1. length ist strikt im ersten Argument:length ⊥ > → caselst ⊥ of . . .→ ⊥. D.h. die Behauptung gilt.

2. length ist strikt im zweiten Argument:

length > ⊥ → caselst > of Nil→ ⊥;x : xs→ length xs (⊥+ 1)→ 〈⊥, length > (⊥+ 1)〉→ 〈⊥, length > ⊥〉

Hier steht 〈⊥, length > (⊥+1)〉 fur eine Vereinigung der beiden Moglich-keiten.

Dies ergibt eine Schleife, also ist das Ergebnis = ⊥.

Aber: Im Beispiel oben haben wir Objekt- und Metalevel-Betrachtungengemischt: Die Nichtterminierung auf der Meta-Ebene haben wir als Nicht-Terminierung auf der Objektebene gedeutet. Es ist nicht offensichtlich, dassdieses Verfahren korrekt ist.

1.4.4 Striktheitstableaus

Um die Korrektheit zu zeigen und zu verstehen, formulieren wir abstrakte Re-duktion als Kalkul, der als Datenstruktur einen Baum benutzt, der im we-sentlichen der Reduktionsbaum der abstrakten Reduktionen und der Fallunter-scheidungen ist. Dieser Baum von Ausdrucken wird auch Tableau genannt. DieAussagen und Beweise beziehen sich dann auf den Kalkul auf einem Tableau.Dazu benotigen wir zunachst abstrakte Ausdrucke (Terme), und spater fur denKorrektheitsbeweis deren Konkretisierungen. Abstrakte Ausdrucke (Terme) inKFPT sind KFPT-Ausdrucke, die um die Konstanten ⊥,> erweitert sind.Wir definieren eine abstrakte Reduktion eines abstrakten Ausdrucks (Terms) tals eine Reduktion des Terms t, wobei man in t die Konstanten ⊥,> behandelt,als waren es Konstanten c⊥, c>.Wir definieren eine abstrakte Normalordnungs-Reduktion eines abstrakten Termst als eine abstrakte Reduktion in Normalordnung.

Definition 1.4.5 Ein Striktheits-Tableau zu einem abstrakten (geschlossenen)Ausdruck t ist definiert als ein markierter endlicher Baum mit:

• die Knoten sind mit abstrakten Termen markiert.

• Die Wurzel ist markiert mit dem zu reduzierenden Term t.

• Wenn der Knoten A genau die Tochterknoten B1, . . . , Bn hat, und dieentsprechenden Terme tA, tBi

sind, dann wurden die Knoten Bi mit einerder Kalkulregeln aus Definition 1.4.6 aus A erzeugt.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 26

Definition 1.4.6 (Kalkulregeln zum Aufbau des Tableaus) Folgende Regelnwerden verwendet:

1. Reduktion: Wenn t → t′ mit abstrakter Reduktion und t eine Markierungeines Blattes B ist, dann kann man t′ als neues Blatt B′ als Tochter vonB anhangen.

2. ⊥-Reduktion: Als weitere abstrakte Reduktionen verwenden wir folgende,wobei der Korrektheits-Beweis unten nur den Fall abdeckt, wenn dieseRegeln nicht innerhalb einer Abstraktion verwendet werden.

• (⊥ t)→ ⊥.

• (caseA ⊥ . . .)→ ⊥ und

• g t1 . . . ti−1 ⊥ ti+1 . . . tn → ⊥, wenn g n-stellig ist und bereits alsstrikt im i-ten Argument bekannt ist.

3. Fallunterscheidung: Wenn (caseA > e1 . . . en) ein Unterausdruck einesTerms t an einem Blatt B ist und n die Anzahl der Konstruktoren furA, dann konnen wir n + 1 neue Blatter Bi, i = 1, . . . , n anhangen, wobeider Ausdruck B0 als ⊥ definiert ist, und die Ausdrucke Bi dadurch, dassjeweils im case -Ausdruck das > durch (cA,i > . . .>), i = 1, . . . n ersetztist.

4. Generalisierung: Wir konnen ein neues Blatt B′ unter B anhangen, wobeit′B gebildet wird aus tB, wobei an einer beliebigen Stelle im Term tB einUnterausdruck durch > ersetzt wurde.

5. Direkt ungetypte Ausdrucke: Wenn am Blatt ein direkt ungetypter Aus-druck an einer strikten Position steht, dann kann man ein Blatt mit ⊥anhangen.

Die Fallunterscheidung sollte man moglichst nur an Normalordnungsredexendurchfuhren, da die Anzahl der Falle sonst unnotig exponentiell wachsen kann.Der ⊥-Fall der Fallunterscheidung ist nicht notig, wie wir spater sehen werden.

Definition 1.4.7 Ein Striktheits-Tableau ist geschlossen, wenn alle Blatter Beine der beiden folgenden Eigenschaft haben:

1. das Blatt ist mit ⊥ markiert, oder

2. das Blatt B ist mit t markiert und hat einen Vorgangerknoten N derebenfalls mit t markiert ist, und auf dem Pfad von N nach B wur-de mindestens einmal ein abstrakter Normalordnungsschritt durchgefuhrt(d.h. nicht nur Nicht-Normalordnungsreduktionen, Fallunterscheidungenund Generalisierungen).In diesem Fall nennen wir den zum Blatt gehorigen Knoten Rekursionva-ter. Falls dieser nicht eindeutig ist, wahlen wir immer den am nachstenzur Wurzel gelegenen Knoten.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 27

Beispiel 1.4.8 Die Funktion f sei definiert durch f x = f (f x). Man sieht,dass diese Funktion nicht terminiert. Ein geschlossenes Striktheits-Tableau siehtso aus:

f >| Normalordnungsreduktion

f (f >)| Generalisierung

f > Schleife

1.4.5 Nachweis der Korrektheit des Kalkuls

Zunachst brauchen wir die Semantik der abstrakten Ausdrucke (Terme).

Definition 1.4.9 Die Konkretisierung γ(t) eines abstrakten Ausdrucks t istdie Menge aller KFPT-Ausdrucke t′, die aus t entstehen durch Ersetzung von>-Konstanten durch beliebige geschlossene Ausdrucke und von ⊥ durch beliebigegeschlossene Ausdrucke die nicht konvergieren; d.h. mit unendlicher Normalord-nungsreduktion oder mit Typfehler.

Beispiel 1.4.10

• case_lst true (nil -> x) (x:xs -> x) ∈ γ(⊥), da der Ausdruck di-rekt ungetypt ist. Weitere Ausdrucke in γ(⊥) sind u.a. (Y Id), da dieNormalordnungsreduktion nicht terminiert, (Nil Nil),. . . .

• γ(>) = Menge aller geschlossenen Terme.

• γ(length > ⊥) = alle Terme der Form (length t1 t2), wobei t1 geschlos-sen ist und t2 ∈ γ(⊥).

Die Schwierigkeit mit den offenen Termen kommt daher, dass z.B. x alleine einAusdruck ist, der keine WHNF hat, aber der nach Einsetzungen in x sowohl ⊥sein kann als auch eine WHNF haben kann.Die Anzahl der Normalordnungsreduktionen von Termen ist dabei das wesent-liche Hilfsmittel.Es gilt:

Lemma 1.4.11 Sei t abstrakter Term, s ∈ γ(t) und t → t′ eine abstrakteNormalordnungs-Reduktion an Position p. Dann kann man s an Position pebenfalls in Normalordnung reduzieren – s→ s′ – und es gilt s′ ∈ γ(t′).

Lemma 1.4.12 Sei t ein geschlossener Term mit t⇓. Dann gilt:

1. Sei eine Reduktion red (von t startend zu einer WHNF) gegeben, wo-bei nur der letzte Term in red eine WHNF ist. Dann ist die Anzahl derNormalordnungsschritte in red ≤ rln(t). Hieraus folgt auch, dass s → timpliziert, dass rln(t) ≤ rln(s) ist.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 28

2. Sei tno−→ t′ mit einem Normalordnungsreduktionsschritt. Dann ist

rln(t) = rln(t′) + 1.

3. Sei s ein echter Unterausdruck von t, so dass ein Normalordnungsredexvon t innerhalb von s liegt.Dann gilt rln(t) > rln(s).

Beweis. Bis auf 3 folgen die Behauptungen aus Aussage 1.1.21. Teil 3 folgt ausder Uberlegung, dass jede Normalordnungsreduktion eines Terms t, die mit einerWHNF endet, auf jeden Fall erst jeden Unterausdruck s zu WHNF reduzierenmuss, der zwischen t und dem Normalordnungsredex von t liegt. 2

Lemma 1.4.13 Sei ein innerer Knoten N mit Markierung t eines geschlosse-nen Tableaus gegeben und sei t0 ∈ γ(t) eine Konkretisierung mit γ(t)⇓. Danngibt es einen Nachfolger N ′ von N mit einer Markierung t′ und t1 ∈ γ(t′); und

es gilt t0 ≡ t1, oder t0∗→ t1.

Beweis. Wir gehen die Kalkulregeln durch. Sei t0 ∈ γ(t).

1. Eine abstrakte Reduktion wurde angewendet, d.h. eine β-, δ- oder case-Reduktion. Dann kann man die gleiche Reduktion fur t0 machen und erhalteine Konkretisierung t1 von t′ (siehe Lemma 1.4.11).

2. Wenn eine ⊥-Reduktion durchgefuhrt wurde, dann ist t0 ebenfalls eineKonkretisierung von t′. Hier ist zu beachten, dass ⊥-Reduktionen nichtinnerhalb von Abstraktionen durchgefuhrt werden durfen und deshalb derRedex keine freie Variable enthalt.

3. Angenommen, eine Fallunterscheidung zum case wurde gemacht.

Wenn der erste Unterausdruck im case-Ausdruck der Konkretisierung di-vergiert, dann kann man den TochterknotenB0 wahlen, bei dem case> . . .durch ⊥ ersetzt wurde.

Wenn der case-Unterausdruck konvergiert, dann gibt es wieder zwei Falle.

Wenn der case-Ausdruck insgesamt nicht getypt ist, dann kann man denB0-Zweig nehmen.

Wenn der Unterausdruck im case den richtigen Typ hat, kann weiterre-duziert werden. Dieser Unterausdruck konvergiert, wobei ein Konstruktordes case-Typs das oberste Symbol des Terms ist. Es gilt die Beh., da maneinen der Knoten Bi wahlen kann. Beachte, dass in diesem der erste Aus-druck durch (c > . . .>) ersetzt wurde.

4. Im Fall der Generalisierung kann man t1 = t0 wahlen.

2

Satz 1.4.14 Wenn fur eine Markierung der Wurzel mit einem Term t sichmit obigen Regeln ein geschlossenes Tableau aufbauen lasst, dann gilt fur alleKonkretisierungen t′ von t dass t′⇑.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 29

Beweis. Annahme, dies sei falsch. Dann gibt es eine Konkretisierung t0 derWurzel, so dass t0⇓. Diese Konkretisierung lasst sich im Tableau verfolgen,entsprechend dem obigen Lemma. Es gibt ein Blatt, das eine konvergierendeKonkretisierung hat. Dieses Blatt kann nicht mit ⊥ markiert sein. Also gibt esein Rekursionsblatt, das einen Term mit WHNF als Konkretisierung hat.Wir wahlen unter den Blattern, die einen Term mit WHNF als Konkretisierunghaben, ein Blatt aus, das eine Konkretisierung t1 mit kleinstem rln(t1) hat. Un-ter diesen minimalen Blattern wahlen wir dasjenige aus, dessen Rekursionvaterminimalen Abstand zur Wurzel hat. Wegen der Bedingungen an geschlosseneTableaux ist die Konkretisierung t1 auch eine Konkretisierung des Rekursions-vaters. Wir verfolgen t1 bis zum nachsten Blatt. Wenn auf diesem Pfad eineabstrakte Normalordnungs-Reduktion durchgefuhrt wurde, dann ist die Kon-kretisierung, die man im Pfad verfolgen konnte, kleiner geworden bzgl. rln(.).Also gab es keine solche abstrakte Normalordnungs-Reduktion. Also muss derRekursionsvater des neuen Blattes noch naher an der Wurzel liegen, da nachBedingung mindestens eine abstrakte Normalordnungs-Reduktion zwischen Re-kursionsblatt und Rekursionsvater liegt. Dies widerspricht der minimalen Wahldes Vaterknotens.

{{{{{{{{

>>>>>>>>>>>>>>>>>>

◦ t1

{{{{{{{{

vv

�{

q◦

{{{{{{{{

CCCCCCCC

��

MC

6

��������

>>>>>>>>

◦ t1

@G

F��������������

//

◦ ◦ ◦

Damit haben wir einen Widerspruch dazu, dass die Wurzel eine Konkretisierungmit WHNF enthalt. 2

Korollar 1.4.15 Wenn man fur einen n-stelligen Superkombinator f ein ge-schlossenes Striktheitstableau fur den Ausdruck f > . . .> ⊥︸︷︷︸

i

> . . .>

︸ ︷︷ ︸n

aufbau-

en kann, dann ist f strikt im i-ten Argument.

Beispiel 1.4.16 Betrachte die folgenden Funktionen, die als Argumente Paarehaben. Die Funktion g ist von der Methode der abstrakten Interpretation nichtals strikt in z erkennbar. Das ist kein Problem fur unsere Methode:

f (x,y) = x+y

g x (y,z) = f (if x then (y,z) else (z,y))

h x y z = g x (y,z)

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 30

Wir nehmen an, dass die Paar-Pattern mittels case kodiert sind, d.h.:

f u = case u of (x,y) -> x+y

g x u = case u of (y,z)-> f (if x then (y,z) else (z,y))

h x y z = g x (y,z)

Die Frage ist jetzt: ist h strikt im dritten Argument?Es ist leicht zu sehen, dass f strikt in beiden Komponenten des Tupels ist. DasTableau fur h > > ⊥ ist wie folgt:

h > > ⊥

g > (>,⊥)

f(if > then (>,⊥) else (⊥,>))

kkkkkkkkkkkkkkkkk

TTTTTTTTTTTTTTTTT

⊥ f(>,⊥) f(⊥,>)

⊥ ⊥Damit ist h als strikt in z erkannt.

Beispiel 1.4.17 Wir untersuchen Striktheit von foldl. Die Definition ist:foldl f z xs = case_lst xs of Nil-> z;y:ys-> foldl f (f z y) ys

Der erste Versuch fur ein Tableau zur Frage der Striktheit im zweiten Argumentsieht so aus:

foldl > ⊥ >

case > . . .

nnnnnnnnnnnnn

SSSSSSSSSSSSSS

case ⊥ . . . case Nil . . . case (>;>) . . .

⊥ ⊥ foldl > (> ⊥ >) >

Daraus kann man nichts weiter schließen, da foldl > > > terminierende Kon-kretisierungen hat. Wenn man aber das Argument f explizit drin lasst und an-nimmt, dass f strikt im ersten Argument ist, dann bekommt man folgendes:

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 31

foldl f ⊥ >

case > . . .

nnnnnnnnnnnn

RRRRRRRRRRRRRR

case ⊥ . . . case Nil . . . case (> : >) . . .

⊥ ⊥ foldl f (f ⊥ >) >

foldl f ⊥ >

oo

��

��

"*

3@

KRW[\^_

Beispiel 1.4.18 Striktheit von foldr. Die Definition ist:foldr f z xs = case_lst xs of Nil-> z;y:ys-> f y (foldr f z ys)

Analog zu foldl nehmen wir an, dass das Argument f explizit bleibt. Fur foldrnehmen wir an, dass f strikt im zweiten Argument ist. Dann bekommt manfolgendes Tableau:

foldr f ⊥ >

case > . . .

nnnnnnnnnnnn

SSSSSSSSSSSSSS

case ⊥ . . . case Nil . . . case (> : >) . . .

⊥ ⊥ f > (foldr f ⊥ >)

oo

%

*1

:FNTX\_

Hier muss man zum Schließen des Tableaus das Kriterium verwenden, dass einUnterausdruck des Terms am Blatt als Rekursionsvater vorkommt und dass derUnterausdruck in einem Reduktionskontext ist, unter Ausnutzung der Striktheitvon f .

Abbruchkriterium: Striktheit kann nicht mehr gefunden werden, wenn fol-gendes gilt

1. wenn ein Blatt eine WHNF als Markierung hat.

2. wenn ein Blatt > als Markierung hat

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 32

Unter bestimmten Bedingungen kann man daraus schließen, dass der Ausdruckan der Wurzel tatsachlich eine WHNF als Konkretisierung hat, (und damit fnicht strikt ist). Bei der Striktheitsanalyse kann man ebenso unter gewissenBedingungen schließen, dass der Kombinator nicht strikt ist. Z.B. wenn wederdie Regel Generalisierung auf dem Pfad zur WHNF verwendet wurde, und wennkein mittels δ- oder Beta-Reduktion kopiertes >-Symbol fur den Nachweis derWHNF benutzt bzw analysiert wurde.

Beispiel 1.4.19 from x := x : from (x+1)

from ⊥ = ⊥ : from (⊥+ 1) hat WHNF. Also ist from nicht strikt.

Beispiel 1.4.20 Folgendes Beispiel zeigt, dass eine Funktion strikt sein kann,obwohl in einem Ast ein > am Blatt steht:

f x y = case x of

True -> y

False -> case x of True -> x

False-> y

f > ⊥ ergibt auf jeden Fall ⊥, da x entweder True, False oder etwas anderesist, wodurch aber das jeweilige case zu ⊥ wird. Die Analyse zu f > ⊥ ergibt imFalse-Fall: case Top of True -> Top; False-> bot, also gibt es ein Blattmit >. Das liegt daran, dass > kopiert wird, und die Information, dass es sichan verschiedenen Stellen um den gleichen Term handelt, dabei verloren geht.In letrec-Kalkulen mit Sharing passiert das nicht.

Beispiel 1.4.21 Ein Beispiel aus der Dissertation [Pap00], leicht abgeandert,da es im Original den Ausdruck case x of x -> True enthalt, der dem strict-Operator in der Sprache entspricht. Die Behauptung dort ist, dass es nur wenigeAnalysemethoden gibt. die zeigen, dass die Funktion strange strikt im zweitenArgument ist.

strange n x y = if e then x else y

where e = case_int n of

0 -> (case_lst x of nil -> False; z:zs -> False);

succ z -> True

Betrachte strange > ⊥ >. Das reduziert abstrakt zu:

if e then ⊥ else >where e = caseint > of

0→ (caselst ⊥ of Nil → False;y : ys → False);

succ z → True

Danach kommt eine Fallunterscheidung zu caseint > . . .. Den ⊥-Fall lassenwir weg.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 33

1.if e then ⊥ else >

where e = caseint 0 of

0 → (caselst ⊥ of Nil → False;y : ys → False);

succ z → True

−→

if e then ⊥ else >where e = (caselst ⊥ of Nil → False)

−→

if e then ⊥ else >where e = ⊥

−→ if ⊥ then ⊥ else >−→ ⊥

2.if e then ⊥ else >

where e = caseint (succ >) of

0 → (caselst ⊥ of Nil → False;y : ys → False);

succ z → True

−→ if e then ⊥ else > where e = True

−→ if True then ⊥ else >−→ ⊥

Damit sind alle Zweige behandelt und die Striktheitsanalyse ist erfolgreich been-det.

Wenn man die Striktheitstableau-Analyse auf die Sprache KFPTS + seq er-weitert, dann muss man nachprufen, dass alle Aussagen uber die Redukti-onslangen noch gelten. Dies Satze gelten jedoch genauso, so dass der Beweisder Korrektheit noch funktioniert. Der Ausdruck seq > t kann allerdings nichtwie ein case behandelt werden, sondern erfordert eigentlich eine erweiterte Fall-unterscheidung. Man sieht aber leicht, dass es ausreicht, die Falle ⊥ und alleanderen WHNFs zu betrachten, so dass sofort eine Normalordnungsreduktionzu seq > t→ t erfolgen kann.

1.4.6 Verbesserungen der Striktheitsanalyse

Die Regel zum Schließen des Tableaus lasst sich verbessern. Einerseits kannman optimieren, andererseits konnen diese Erweiterungen bewirken, dass mehrabstrakte Terme als zu ⊥ aquivalent nachgewiesen werden. Die Beschreibungdes Kalkuls verkompliziert sich dadurch.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 34

Wir definieren eine (Subsumtions-) Ordnung auf Ausdrucken, die im wesentli-chen die Ordnung ⊥ ≤ s ≤ > mit Kontexten kompatibel macht.

1. s ≤sub s fur alle s.

2. s ≤sub > fur alle s.

3. ⊥ ≤sub s fur alle s.

4. Sei C[] ein Kontext und s ≤sub t. Dann soll auch C[s] ≤sub C[t] gelten.

Intuition hier ist, dass r eine Konkretisierung von s ist und s ≤sub s′, unds hat Reduktionslange n, dann gibt es ein r′ als Konkretisierung von s′ dieebenfalls Reduktionslange n hat. Da z.B. auch ⊥ ≤sub > : >, muss man dieKonkretisierung-Definition etwas erweitern, s.u.

Definition 1.4.22 Im erweiterten Striktheitstableau-Kalkul erlauben wir fol-gende Regeln:

• (Improvement-Anwendung): Wenn t eine Markierung an einem Blatt istund t′ � t, dann hange eine neues Blatt an mit der Markierung t′.

• Verbesserte Schlussregeln: Folgende Blatt-Abschlussregeln sind nochzusatzlich erlaubt:

– Das Blatt B mit Markierung t ist abgeschlossen, wenn es einenVorganger N mit Markierung t′ gibt und t ≤sub t

′, und wenn zwi-schen N und B eine abstrakte Normalordnungs-Reduktion durch-gefuhrt wurde.

– Das Blatt B mit Markierung tB ist abgeschlossen, wenn es einenVorganger N mit Markierung tN gibt und einen echten Unteraus-druck t′B von tB, so dass t′B in einem Reduktionskontext ist (Erwei-terung: an einer strikten Position). D.h. t′B wird auf jeden Fall redu-ziert, wenn tB zu WHNF reduziert wird. Zusatzlich muss t′B ≤sub tNsein.

• Die case-Fallunterscheidung wird eingeschrankt: der ⊥-Fall muss nichtmehr betrachtet werden, er wird durch die Subsumtionsordnung erledigt:er ist immer redundant.

Begrundung fur die Korrektheit: Man muss den Satz 1.4.14 und den Beweisdieses Satzes an die neuen Regeln anpassen. Ebenso die Lemmas, die im Beweisverwendet werden.Hierzu muss man den Begriff “Konkretisierung“ abandern zu:

Ein Term ist ≤sub -Konkretisierung von t, wenn er ≤sub eine Kon-kretisierung ist. D.h. t0 ∈ γsub(t) gdw. ∃t1 : t0 ≤sub t1 ∈ γ(t)

Es gilt dann z.B. dass s ≤sub t⇒ γsub(s) ⊆ γsub(s).Eine weitere Veranderung der Beweise ist die Verwendung des Teils 3 von Lemma1.4.12, ebenso wie die Verwendung der Improvement-Relation.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 35

Beispiel 1.4.23 Die Funktion (takeuchi) wird z.T. als Benchmark verwendet,um die Effizienz des Funktionsaufrufs in einer Implementierung einer Program-miersprache zu testen.

tak x y z = if x <= y

then z

else tak (tak (x-1) y z)

(tak (y-1) z x)

(tak (z-1) x y))

Lemma 1.4.24 tak ist strikt in allen Argumenten:

Beweis.

1. tak ⊥ > > → if ⊥ ≤ > then . . . else . . .) → ⊥, da ≤ strikt in denbeiden Argumenten ist.

2. tak > ⊥ > → if > ≤ ⊥ . . .→ ⊥, da ≤ strikt in den beiden Argumentenist.

3.

tak > > ⊥→ if > ≤ > then ⊥ else

(tak(tak (>− 1) > ⊥)(tak (>− 1) ⊥ >)(tak (⊥− 1) > >))→ if > then ⊥ else

(tak(tak (>− 1) > ⊥)(tak (>− 1) ⊥ >)(tak (⊥− 1) > >))→ 〈⊥, tak(tak (>− 1) > ⊥)(tak (>− 1) ⊥ >)(tak (⊥− 1) > >))〉→ 〈⊥, tak(tak (>− 1) > ⊥) ⊥ (tak (⊥− 1) > >))〉→ 〈⊥〉

Der letzte Schritt gilt, da vorher bereits nachgewiesen wurde, dass tak strikt inden ersten beiden Argumenten ist. Insgesamt ist tak strikt in allen Argumenten.2

1.4.7 Implementierung der Striktheitsanalyse

Benutzung einer Variante einer Reduktionsmaschine statt eines Tableaus:

• 〈s1, . . . , sn〉 ist eine syntaktische Vereinigung. Die Operation erfolgt aufdieser Datenstruktur.

• Hierauf wird jeweils ein Reduktionsschritt durchgefuhrt.

• Es wird mit der Ordnung ≤sub eine Maximierung auf der Vereinigungdurchgefuhrt.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 36

Problem: Ist diese Implementierung korrekt?Diese Implementierungsmethode kann man als Striktheits-Tableau-Methode an-sehen, die auf einem gerichteten Graphen arbeitet statt auf einem Baum, undbei der als zusatzliche Schlussregel verwendet wird:

Das Blatt B mit Term t ist geschlossen, wenn es einen Knoten N mitTerm t′ gibt, und t ≤sub t

′ gilt (der Knoten N muss nicht notwendigein Vorganger sein ) und es wird eine gerichtete Kante von B nachN eingefugt.

Hierbei darf N irgendein Knoten sein. Die Idee dahinter ist, dass der Termi-nierungstest fur den Knoten N schwerer ist als fur B, deshalb testet man nurN .Damit man das Tableau geschlossen nennen darf, muss allerdings noch folgendeBedingung erfullt sein, die dafur sorgt, dass man das Problem nicht innerhalbeines Zyklus vor sich herschiebt: Es darf keinen Zyklus der folgenden Art geben:B1, N1, B2, N2, . . . , Bn, Nn, Bn+1 mit Bn+1 = B1, so dass fur alle i

• Bi ≤sub Ni mit obiger Regel, oder Bi hat Rekursionvater Ni mit gleichenTermen

• Ni ist Vorganger von Bi+1 und der Pfad von Ni zu Bi+1 ist ohne abstrakteNormalordnungsreduktionen.

Im Bild, wobei gestrichelte Linien die Beziehung ≤sub andeuten sollen.

R

{{{{{{{{

CCCCCCCC

N0

≤sub

QQQQQQQQ N1

≤sub||

||

N2

≤sub||

||

B1 B2 B3

Diese Bedingung kann man auch einfach formulieren, wenn man die gerichtetenKanten des Tableaus mit einbezieht: Dann darf es keinen Zyklus geben, derweder eine Normalordnungskante hat noch eine strikte Subterm-Kante.

Diese Bedingung, dass es keine solchen Zyklen gibt, erlaubt zu schließen, dassrln(t0) in einem Zyklus ohne die Nebenbedingungen wirklich verkleinert wird.Man kann die obige Bedingung durch einfachere lokale Bedingungen ersetzen,die dann allerdings etwas schwacher sein konnten.Hieraus kann man Schlusse uber die Implementierung ziehen und erkennen,worauf zu achten ist.

1. Bei Sharing von Termen: Normalerweise werden Terme uber Pointer ge-meinsam verwendet. Wenn ein Term reduziert wird, dann kann dies imTableau eine Reduktion mehrerer Blatter bedeuten.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 37

2. Beim Suchen der Rekursionsvater muss man beachten, dass die alten Mar-kierungen, d.h. Markierung nicht an den Blattern, nicht mehr reduziertwerden durfen.

1.4.8 Anwendungen der Striktheitsanalyse

Im Glasgow Haskell Compiler und im HBC sind Striktheitsanalyser eingebaut.Der Effizienzgewinn ist merklich. Allerdings sind bestimmte einfache Strikt-heitsanfragen bereits in den Kompilierschemata fur die G- bzw. STG-Maschineenthalten, und benotigen keine Unterstutzung durch die Striktheitsanalyse.Eingepackte Werte (Boxed values) sind mit Indirektion versehene Zahlen,Boolesche Werte usw. Zur Optimierung verwenden die Haskell-Compiler aus-gepackte (pure) Werte (unboxed values) zur Laufzeit. Diese lassen sich evtl. inRegister zwischenspeichern. Die abstrakten Maschinen sehen fur diese Werteeinen eigenen Stack vor (Z.B. ABC-Maschine von Clean) bzw. eine extra Be-handlung. Damit der Compiler die Erlaubnis hat, diese zu verwenden, mussbekannt sein, dass zu bestimmten Zeitpunkten diese Werte nicht nur potentiell,sondern ausgewertet vorliegen. Diese Information kann die Striktheitsanalyseliefern.Parallelisierung. Damit man parallelisieren kann, ohne spekulative Auswer-tung zu verwenden, benotigt man Information uber die Auswertungsreihenfolgeund ob Auswertung benotigt wird. Z.B wenn der Wert von (s+t) benotigt wird,kann man zunachst s, dann t auswerten. Da aber beide garantiert ausgewertetwerden mussen, kann man s und t auch parallel auswerten. Dies liegt daran,dass + strikt in beiden Argument ist. Allgemeiner genugt es zu wissen, dass eineFunktion f strikt in bestimmten Argumenten ist. Wenn der Wert von (f t1 . . . tn)benotigt wird, kann man die Ausdrucke an den strikten Argumentstellen paral-lel auswerten. Allerdings ist dies in der Praxis nicht so einfach, denn das naiveAusnutzen kann zu viele kleine Prozesse erzeugen, die keinen Effizienzgewinnbringen. Das korrespondiert zur moglicherweise schlechteren Platzkomplexitatbei Ausnutzen der Striktheit. D.h. bei Parallelisierung ist neben der Striktheitdie Granularitat (Anzahl und Große der Prozesse) ebenfalls zu beachten.

1.4.9 Charakteristische Menge einer Auswertungsmetho-de

Algorithmen oder Verfahren, die einen Ausdruck t “von oben“ her bis zu einerWHNF oder auch weiter auswerten, nennen wir Auswertungsmethode. Zum Bei-spiel ist die Normalordnungsreduktion eine solche Auswertungsmethode. Auchein Superkombinator S, angewendet auf einen Ausdruck t, bewirkt eine Aus-wertung von t, wenn man S t mit Normalordnungsreduktion auswertet.Eine durch einen Superkombinator vermittelte Auswertung nennen wir sequen-tiell. Im folgenden interessiert uns nur die Auswertung des oberen “Datenanteil“eines Ausdrucks. Wir ignorieren die Auswirkung auf Abstraktionen.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 38

Fragestellung: Wenn S Superkombinator, wieviel darf man von n-ten Argu-ment bereits vorher auswerten?

Beispiel 1.4.25 Bei hd darf man das Argument zur WHNF t1 : t2 auswertenund auch t1 darf man auswerten (ohne einen semantischen Fehler zu machen).Aber t2 darf man nicht auswerten.Bei length darf man das Ruckgrat der Argument-Liste vorher auswerten, abernicht die Elemente der Liste.

Idee: Nutze Striktheitsanalyse bzw. Nichtterminierungsanalyse fur(S > . . . > D︸︷︷︸

n

> . . .>) wobei D eine gute Testmenge fur die Auswer-

tungsmethode A ist.

Wenn Nichtterminierung nachgewiesen, darf man die Auswertungsmethode Aauf das nte Argument anwenden vor Auswertung (S t1 . . . tm)

Gegeben einen bereits teilweise ausgewerteten Ausdruck t, kann man die Mengeder Unterausdrucke, die als nachstes ausgewertet werden konnen, so definieren:AuswertbareUnterausdruecke(t) =

• {t} wenn t nicht in WHNF

• ∅ wenn t in FWHNF

•⋃

i=1,...,ar(c) AuswertbareUnterausdruecke(t) wenn t eine CWHNFc t1 . . . tar(c) ist.

Normalerweise besteht ein Schritt einer deterministischen Auswertung darin,dass der bisherige Auswertungszustand inspiziert wird und dann ein weiterer,bisher nicht ausgewerteter Term unterhalb der Auswertungsgrenze ausgewertetwird, d.h. ein Term in AuswertbareUnterausdruecke(t).Es gibt auch eine parallele bzw nicht-deterministische Variante, die wir hier abernicht weiter betrachten.Beachte, dass die Auswertung den Ausdruck t zu einem “unendlichen Objekt“machen kann.Die Wirkung einer deterministischen Auswertungsmethode auf die Argumentekann man in vielen Fallen, auch solchen, in denen diese Auswertung nicht durcheinen Superkombinator bewirkt wird, beispielsweise eine parallele Auswertung,folgendermaßen charakterisieren:Informell kann man eine Auswertungsmethode so charakterisieren:

Sei E eine deterministische Auswertungsmethode und M eineMenge von geschlossenen Ausdrucken.

E ist die zu M korrespondierende Auswertung,gdw.

M = NT (E) := {e | e geschlossen und (E e) hat keine WHNF }

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 39

Im allgemeinen beschranken wir uns auf solche Mengen, die zu einer (poly-morph) getypten Sprache passen.

Sei S ein Superkombinator in KFPTSP mit einem Typ T → Bool,wobei T keine Pfeil-Typen enthalt, und M eine Menge von geschlos-senen Ausdrucken.Die charakteristische Menge zur Auswertung durch S ist

NT (S) := {e | e geschlossen und (S e)⇑}

Die Menge NT (E) der geschlossenen Terme, fur die (E e) nicht konvergiert,kann man manchmal durch eine Untermenge (d.h. eine Annaherung bzw einenAbschluss) darstellen, die aber fur unsere Zwecke das gleiche leistet (Nachweisist im Skript der CEFP).

1.4.10 Erweiterungen: neue abstrakte Werte

Andere, endliche Darstellungen kann man durch Ausdrucke mit ⊥,> undKonstruktoren erhalten. Hierbei machen wir die Vereinfachung, dass dieAbstraktionen ignoriert werden, d.h. das es formal nur fur getyptes KFPT, d.h.KFPTSP, korrekt ist. Will man das ungetypte definieren, z.B. in KFPT(S),dann braucht man eine weitere Konstante Fun, die alle Abstraktionen re-prasentiert.

Eine Grammatik dazu ist

D ::= ⊥ | > | (c D1 . . . Dn) | 〈D1, . . . Dn〉

wobei c ein n-stelliger Konstruktor ist, und die semantische Bedeutung von〈D1, . . . Dn〉 die Vereinigung ist.Wir werden eine weitere Variante verwenden, die Namen erlaubt:

• Es gibt eine unendliche Menge N von Namen zu Demands.

• Demands D sind aufgebaut entsprechend der Grammatik:D ::= ⊥ | > | N | (c D1 . . . Dn) | 〈D1, . . . Dn〉

Die Semantik ist:

• γ(⊥) := Menge der divergierenden geschlossenen Ausdrucke.

• γ(>) := Menge aller geschlossenen Ausdrucke.

• γ((c D1 . . . Dn)) := Menge aller geschlossenen Ausdrucke der Form(c s1 . . . sn) mit si ∈ γ(Di) und wobei c ein Konstruktor ist.

• γ(〈D1, . . . Dn〉) :=⋃

i γ(Di).

• γ(N) ist kleinster Fixpunkt der Definitionsgleichungen fur die Demandna-men.

SAFP, WS 2014/15, Striktheits-Analyse vom 10.1.2015 40

Die formale Definition erganzt dann diese Definitionen durch einen Abschlussbzgl kontextueller Approximation.

Beispiel 1.4.26 Wir konnen jetzt schon solche Mengen hinschreiben und schonZusammenhange andeuten:

1. ⊥ beschreibt die WHNF Auswertung:Zu ⊥ gehort die Menge der Ausdrucke, deren Normalordnungs-Auswertung nicht mit einer WHNF terminiert.

2. 〈⊥, Nil,⊥ : >〉 beschreibt den sinnvollen Anteil der Auswertung, die eineListe zu WHNF auswertet, und, falls es eine nichtleere Liste ist, das ersteElement ebenfalls auswertet. Ist diese Auswertung durch einen Superkom-binator definiert (hd), dann mussten es eigentlich auch solche Elementesein, die die (dynamische) Typisierung verletzen, z.B. True.

3. Die Ruckgratauswertung ist die Auswertung, die eine Liste zu WHNF aus-wertet und danach rekursiv wieder den Tail genauso behandelt.

Die geschlossenen Listenausdrucke, fur die die Ruckgratauswertung nichtterminiert. kann man annahern mit 〈⊥,> : ⊥,> : > : ⊥, . . .〉. Die rekur-sive Definition Inf = 〈⊥,> : Inf〉 beschreibt diese Menge. Diese Mengebesteht aus allen Listen mit ⊥-Tail.Man kann diese Menge bzw diese Beschreibung als Testmenge verwen-den.Man kann nachweisen (siehe Artikel dazu), das Inf ausreichend ist. D.h.es approximiert alle Listenausdrucke (unter Benutzung von club), bei de-nen man bei der (programmierten) Suche nach dem iterierten Tail niemalsauf ein Ende (d.h. ein Nil) stoßt. Damit sind auch alle “unendlichen“ Li-sten erfasst.

Zum Beispiel ist (repeat 1) nicht direkt erfasst; aber es wird von Inf

approxomiert.Genauer und verstandlicher: Wenn fur eine definierte Funktion f , alleAnwendungen f r fur alle Ausdrucken r aus Inf nicht terminieren, dannkann (f r) auch nicht terminieren fur alle potentiell unendlichen Listenr.

Die Charakterisierung durch das komplementare Verhalten ist zunachst nichtintuitiv, erweist sich aber als sehr praktisch, denn die zugehorigen Mengenbe-schreibungen, die Demands, sind leicht rekursiv zu beschreiben und zu verar-beiten und sie haben die richtigen Eigenschaften. Mehr Information ist in derDissertation [Sch00].Man kann mit erweiterten Demands auch Mengen darstellen, die keiner Aus-wertung entsprechen: Z.B. {t | t hat Nil als WHNF } ist eine solche Menge.Eine andere ist die Menge der endlichen Listen:

Fin = 〈Nil,> : Fin〉

SAFP, WS 2014/15, Striktheits-Analyse vom 19.1.2015 41

Fin entspricht keiner Auswertung im obigen Sinne, denn das Element ⊥ fehlt.Es gibt auch tatsachlich keine Auswertungsfunktion, die genau auf endlichenListen nicht terminiert.

1.4.11 Allgemeinere Formen von Striktheiten

Eine Moglichkeit der Erweiterung ist die Frage nach “tiefer“ Striktheit, Hy-perstriktheit, bedingter Striktheit, oder die Frage nach Striktheit in mehrerenPositionen.

• Die Auswertungsanforderung “werte die Liste und dann das erste Elementdes Listenargumentes aus“: entspricht z.B. hd mit hd (x:xs) = x. Diesentspricht dem abstrakten Wert (Demand) 〈⊥, Nil,⊥ : >〉

• Tail-strikt: Diese Anforderung wertet (rekursiv) den gesamten Tail derListe aus. Dies entspricht dem abstrakten Wert (Demand) Inf.

• hyperstrikt: Diese Anforderung wertet zur hyperstrikten Normalform (d.h.(Daten-) Normalform) aus. Eine hyperstrikte Normalform ist ein Aus-druck, der aus Konstruktoren und Abstraktionen besteht, entsprechendder Definition: HSNF ::= λx.s | (c HSNF . . .HSNF ).

Tailstriktheit

einer Funktion im Argument i bedeutet, dass diese Funktion das Listenargumentxi auf jeden Fall bis zum Listenende auswertet. Diese Eigenschaft kann manmittels der Methode der abstrakten Reduktion folgendermaßen zeigen: Mannimmt Inf mit Inf := 〈⊥,> : Inf〉 als abstrakten Wert, der als Test fur dietailstrikte Verarbeitung von Listen dient mitD.h. Inf ist rekursiv definiert als eine Vereinigung von ⊥ und > : Inf.Diesen Wert Inf nimmt man jetzt statt ⊥ an der interessierenden Argumentstel-le. Mit dem abstrakten Wert beschreibt man eine Testmenge, die die tailstrikteAuswertung durch Nichtterminierung anzeigt.

Definition 1.4.27 Zu abstrakten Werten mit einer Definition W =〈W1, . . . ,Wn〉n, gibt es eine extra Fallunterscheidungsregel:

C[W ]

C[W1] | . . . | C[Wn]

Diese sollte man bevorzugt an Stellen verwenden, an denen eine abstrakte Nor-malordnungsreduktion ermoglicht wird.

Eine tail-strikte Funktion kann bzgl der Platzkomplexitat verschiedenes Verhal-ten zeigen. Die optimale Variante tritt ein, wenn diese uber eine sehr große Listelaufen soll, und dies mit konstantem (oder logarithmischem) Platz durchfuhren

SAFP, WS 2014/15, Striktheits-Analyse vom 19.1.2015 42

kann (Scan). Wenn man zu strikt programmiert hat, kann es sein, dass dieseFunktion einen linearen Platzbedarf hat, und man im wesentlichen die ganzeListe gleichzeitig im Speicher halten muss. In dem Fall ist es unmoglich, dieFunktion auf ein Argument anzuwenden, das zu einer sehr großen Liste auswer-tet.Wenn man mit Stromen programmiert, ist es eine interessante Information, obeine Funktion tail-strikt ist oder nicht. Denn tail-strikte Funktionen kann mannicht auf Strome anwenden. Z.B. length ist tail-strikt, kann also mit Stromennicht umgehen, wahrend map nicht tail-strikt im zweiten Argument ist.Mit der Tableaumethode kann man zeigen, dass Funktionen tail-strikt sind, alsoungeeignet fur Strome, aber nicht dass sie geeignet sind. Dafur benotigt manandere Methoden.

Beispiel 1.4.28 Eigenschaften der iterativen Variante von length.

length lst s = case_lst lst of nil -> s; x:xs -> length xs (s+1)

Behauptung: Die Funktion length ist tailstrikt im ersten Argument.

length Inf >

caselst Inf (Nil→ >) (x : xs→ length xs (>+ 1))

fffffffffffffffffffffffff

caselst ⊥ . . . caselst (> : Inf) (Nil→ >) (x : xs→ length xs (>+ 1))

⊥ length Inf (>+ 1)

length Inf > Schleife!

Wir geben weitere Beispiele an:

Beispiel 1.4.29 reverse xs = case_lst xs of nil -> nil; x:xs -> (reverse xs) ++ [x]

Diese Funktion dreht eine Liste um. Wir verwenden wieder

Inf := 〈⊥,> : Inf〉.

Wir zeigen mit Striktheitsanalyse, dass reverse die Liste tailstrikt verarbeitet:

SAFP, WS 2014/15, Striktheits-Analyse vom 19.1.2015 43

reverse Inf

caselst Inf of Nil→ Nil;x : xs→ (reverse xs) ++ [x]

gggggggggggggggggg

caselst ⊥ . . . (reverse Inf) ++ [>]

⊥ caselst (reverse Inf) of Nil→ [>];x : xs→ (reverse xs) ++ [x]

Schleife, da Vorgangerausdruck an strikter Position

und da ++ strikt im ersten Argument ist.

Hyperstriktheit

lasst sich folgendermaßen analysieren:

Man benotigt einen abstrakten Test-Ausdruck, der zur Hyperstriktheit passt.

HS = 〈 ⊥,cons1 HS > . . .>︸ ︷︷ ︸

ar(cons1)

, cons1 > HS > . . .>, . . . , cons1 > . . .> HS,

. . . ,consn HS > . . .>︸ ︷︷ ︸

ar(consn)

, consn > HS > . . .>, . . . , consn > . . .> HS,

Hierbei lauft consi uber alle im Programm vorkommenden Konstruktoren, dienicht nullstellig sind. Die nullstelligen Konstruktoren durfen nicht in HS sein,denn deren Auswertung ist bereits durch das ⊥ abgedeckt. Aus dem gleichenGrund darf Fun (FWHNF) nicht in HS sein.Da hierbei auch ungetypte Ausdrucke eine Rolle spielen, muss man beachten,dass man direkt ungetypte Ausdrucke zu ⊥ machen kann bei der abstraktenReduktion.Der obige abstrakte Ausdruck beschreibt die Ausdrucke, die man mittels Aus-wertung von oben nicht zu Normalform auswerten kann. Hier ist eine Auswer-tung gemeint, die Daten vollstandig auswertet, aber nicht unter λ auswertet.

SAFP, WS 2014/15, Striktheits-Analyse vom 19.1.2015 44

Der Ausdruck HS enthalt alle geschlossenen Ausdrucke, die eine undefinierteStelle haben, und approximiert solche, die in mindestens einer

”Richtung“ un-

endlich tief auswertbar sind.

Beispiel 1.4.30 sum s xs = case_lst xs (nil ->s) (y:ys -> sum (s+y) ys)

Beh: sum ist hyperstrikt in xs. Hierbei gehen wir davon aus, dass die Zahlen inPeano-Kodierung vorliegen, und HS entsprechend wie oben definiert ist, dass sumbereits als strikt im ersten Element gezeigt wurde, und dass + bereits als hyper-strikt (bzw. strikt im ersten und zweiten Argument) gezeigt ist. (Die ungetyptenFalle sind weggelassen)

sum > HS

caselst HS (Nil→ >);(y : ys→ (sum (>+ y) ys))

oooooooooooooo

UUUUUUUUUUUUUUUU

⊥ caselst (> : HS) (Nil→ >);(y : ys→ (sum (>+ y) ys))

caselst (HS : >) (Nil→ >);(y : ys→ (sum (>+ y) ys))

sum (>+>) HS sum (>+ HS) >

+ ist hyperstrikt

sum > HS sum ⊥ >

sum ist strikt in 1.

Schleife ⊥

1.4.12 Wadlers 4-Punkt-Domain-Analyse

Der Basisartikel ist [Wad87].Diese Analyse von listenverarbeitenden Funktionen basiert auf einem Domainmit 4 Elementen und benutzt abstrakte Interpretation. Diese Analyse soll hierkurz erlautert werden und dann gezeigt werden, dass man mit der Methodeder Striktheitstableaus die Information, die diese Analyse liefert, ebenfalls (imPrinzip) berechnen kann.Die 4PD-Analyse kann teilweise mehr herleiten als die Striktheitstableau-Methode, denn mit der 4-Punkt-Domain-Analyse kann man den Wert von Funk-tionen auf dem Domain berechnen (bzw approximieren), nicht nur die Verwen-dung von Datenstrukturen testen. Wenn man allerdings die abstrakten Werte indie Striktheitsanalyse einbettet, und in gewissen Fallen Hilfsfunktionen verwen-det, dann ergibt sich die gleiche Information. Die 4PD-Analyse liefert weniger,

SAFP, WS 2014/15, Striktheits-Analyse vom 19.1.2015 45

wenn auch Fallunterscheidungen uber andere Datentypen notwendig zum exak-ten Berechnen sind.Diese Analyse wollen wir hier zum besseren Verstandnis in den Rahmen dersyntax-basierten Analysen stellen.Wir stellen diese 4 Werte als abstrakte Werte dar:

1. ⊥. Menge der nichtterminierenden Ausdrucke. Das entspricht Auswertungzu WHNF.

2. ⊥∞: ist dasselbe wie Inf. D.h. alle Listenausdrucke bei denen die rekursiveAuswertung des Tails nicht terminiert. Das entspricht Auswertung desRuckgrats einer Liste.

3. ⊥ε: Darstellbar als ⊥ε := 〈⊥,⊥ : >,> : ⊥ε〉. Das ist die Menge allerListen, die keine WHNF haben, oder in denen mindestens ein Elementdivergiert. Dies entspricht Auswertung einer Liste und aller Elemente zuWHNF. Dies wiederum entspricht dem HS eingeschrankt auf Listen undderen Elemente.

4. >ε endliche Listen, in denen jedes Element konvergiert. Dies hat keineEntsprechung als Auswertung.

(Wir werden diesen Wert hier nicht verwenden; bzw. ersatzweise > ver-wenden. Um diesen abstrakten Wert zu verwenden musste man auchden Ansatz (Nichtterminierungsnachweis) und den Beweis der Korrekt-heit abandern.) )

Die Ordnung auf dem Domain ist: ⊥ ≤ ⊥∞ ≤ ⊥ε ≤ >ε. Zu beachten ist,dass diese Ordnung nicht direkt mit der Vorstellung als Menge von Ausdruckenzusammenhangt, und dass diese hier auch nicht verwendet wird.

Beispiel 1.4.31 sum s xs = case_lst xs (nil -> s) (y:ys -> sum (s+y) ys)

Die endrekursive Funktion sum wertet das Argument xs aus entsprechend ⊥ε

(wie HS):

SAFP, WS 2014/15, Striktheits-Analyse vom 19.1.2015 46

sum > ⊥ε

caselst ⊥ε (Nil→ >)(y : ys→ sum (>+ y) ys)

pppppppppppppp⊥:>

>:⊥ε

UUUUUUUUUUUUUUUU

⊥ caselst (⊥ : >) (Nil→ >);(y : ys→ (sum (>+ y) ys))

caselst (> : ⊥ε) (Nil→ >);(y : ys→ (sum (>+ y) ys))

sum (>+⊥) > sum (>+>) ⊥ε

sum ⊥ > sum > ⊥ε

⊥ Schleife

In allen Fallen ergibt sich ⊥ oder eine Schleife, somit ist Nichtterminierunggezeigt, und wir wissen: die Funktion sum wertet im Listenargument die Listeund jedes Element der Liste zu WHNF aus.Dieses Wissen konnte man verwenden, um vor der Auswertung von sum bereitsTeile der Argumentliste und deren Element zu evaluieren.

Beispiel 1.4.32 Die 4PD-Analyse kann zeigen, dass map f : Inf → Inf. Umdas mit Striktheitsanalyse zu zeigen, konnte man folgende Idee verwenden:Man braucht die (eine) Auswertungsfunktion istliste, die zu Inf passt:

istliste xs = case_lst xs of Nil -> True; y:ys -> istliste ys

map f xs = case_lst xs of Nil -> Nil; y:ys -> f y : map f ys

Wenn wir zeigen konnen, dass istliste(map > Inf) = ⊥ ist, dann hatten wirdie gleiche Information wie map : Inf → Inf. Um das schließen zu durfen, istallerdings noch Arbeit in die Begrundung zu stecken, eine genaue Behandlungder ungetypten Ausdrucke, und evtl. eine Abanderung des Kalkuls bzgl. ungety-pten Ausdrucken.Ein passendes (geschlossenes) Tableau sieht so aus:

SAFP, WS 2014/15, Striktheits-Analyse vom 19.1.2015 47

istliste (map > Inf)

istliste (caselst Inf (Nil→ Nil)y : ys→ (> y) : (map > ys))

⊥jjjjjjjjjjjjjj

>:Inf

(istliste ⊥) istliste ((> >) : map > Inf)

⊥ (case ((> >) : map > Inf) . . .)

istliste (map > Inf)

Schleife

Die 4PD-Analyse kann zeigen, dass fur terminierende Funktionen f folgendesgilt: map f : >ε → >ε. Die Striktheitsanalyse kann das nicht zeigen, da es furendliche Listen keine charakteristische Auswertungsfunktion gibt. Umgekehrtkann die 4PD-Analyse manche Beziehungen nicht herleiten, da sie den typi-schen Beschrankungen der abstrakten Interpretation unterliegt: die abstrakteInterpretation der Unterfunktionen ist zu verwenden.

Bemerkung 1.4.33 Die Funktion length angewendet auf die Testmenge ⊥ε

ergibt, dass eine WHNF moglich ist. Z.B. ist ⊥ : Nil ∈ γ(⊥ε). Die Anwen-dung von length ergibt 2. Man sieht auch dass die Funktion length mit dieserMethode nicht als hyperstrikt nachgewiesen werden kann (und es auch nicht ist).

Beispiel 1.4.34 Ein weiteres Beispiel ist die Funktion f mit den Definitionen

f xs = length (concat xs)

concat xs = case_lst xs of Nil- > Nil; (y:ys) -> y ++ (concat ys)

von der man zeigen kann, dass sie jede Liste und alle Elemente (das sind Listenals Elemente) auswertet. Dazu muss man das Tableau fur (length(concat xs))berechnen. Wir benutzen ⊥ε := 〈⊥,⊥ : >,> : ⊥ε〉.Mit der Wurzel (length(concat ⊥ε)) ergibt sich fur die ersten beiden Alterna-tiven jeweils leicht ⊥. Bei der dritten erhalt man:(length(concat > : ⊥ε)), danachlength(> ++ (concat ⊥ε))Hier muss man drei Falle betrachten:

SAFP, WS 2014/15, Striktheits-Analyse vom 23.1.2015 48

1. ⊥: In diesem Fall ist das Ergebnis sofort ⊥.

2. Nil: in dem Falle ergibt sich (length(concat ⊥ε)), der Ausdruck an derWurzel, und man kann den Pfad abbrechen.

3. > : >. In diesem Fall ergibt sich nach zwei Reduktionen: 1 +length(> ++ (concat ⊥ε)) und man kann mit dem Unterausdruckkri-terium abbrechen.

Weitere Beispiele und Information kann man [SSSS07, Sch00] entnehmen.

1.4.13 Baume und Analyse

Beispiel 1.4.35 Die Haskell Notation zur Datenstruktur eines einfachenbinares Baumes ist:

data Tree a = Leaf a | Node (Tree a) (Tree a)

wobei Leaf und Node die Konstruktoren sind. Wir nehmen an, dass es nur dieBaume und Boolesche Werte gibt. Wir betrachten die eingeschrankte Menge derWHNFS vom Typ (Tree Boolean). Einige Demands sind:

Tr = ⊥ ∪ (Leaf B) ∪ (Node Tr Tr) (entspr. >Tree)B = ⊥ ∪ True ∪ False (entspr. >Bool)BF = ⊥ ∪ FalseBT = ⊥ ∪ TrueTF = ⊥ ∪ (Leaf BF) ∪ (Node TF TF)TT = ⊥ ∪ (Leaf BT) ∪ (Node TT Tr) ∪ (Node TF TT)TInf = ⊥ ∪ (Leaf ⊥) ∪ (Node TInf Tr) ∪ (Node Tr TInf)TInf2 = ⊥ ∪ (Leaf ⊥) ∪ (Node TInf2 TInf2))TT2 = ⊥ ∪ (Leaf BT) ∪ (Node TT Tr) ∪ (Node Tr TT2)

Der Demand TT korrespondiert zu einer Funktion fTrue∈, die einen Baum vomTyp (Tree Boolean) von links nach rechts durchscannt und ja sagt, wenn sieein Blatt mit Wert True findet. D.h. die Analyse zeigt an, dass fTrue∈ TF nichtterminiert.Der Demand TInf korrespondiert zu einer Funktion die die Anzahl der Blatterzahlt. D.h. die Auswertung ist: werte alle inneren Knoten aus, inklusive Blatter,aber nicht die Inhalte der Blatter.Der abstrakte Wert TInf2 entspricht nicht dieser Auswertung:, denn auch ei-ne Funktion die das erste Blatt sucht, wurde hier nichtterminieren. Genauer:TInf2 entspricht der Auswertung: werte irgendein Blatt aus: das ist aber keineAuswertung die zu einer deterministischen Funktion bzw Superkombinator passt.Die Inklusion TInf ⊆ TF gilt, aber dies kann nicht von der ≤sub-Relation er-kannt werden. Zum Beispiel gilt auch dass TT2 = TT ist.

SAFP, WS 2014/15, Striktheits-Analyse vom 23.1.2015 49

Beispiel 1.4.36 Dieses Beispiel soll den Unterschied der Testmengen TInf undTInf2 illustrieren. TInf ist die Testmenge fur die Auswertung eines Baues unddie Inhalte aller Blatter, wahrend TInf2 zu keiner Auswertung (in KFPT) korre-spondiert. Wenn man nichtdeterministische Auswahl zulasst wahrend der Aus-wertung, dann entspricht TInf2 der Auswertung: Wahle nichtdeterministischeine Pfad zum Blatt und werte den Inhalt aus.

ersterWert xs = case xs of (Leaf a) -> a;

(Node k1 k2) -> ersterWert k1

Es ist auch klar, dass ersterWert nicht den ganzen Eingabe-Baum und alleBlattwerte auswertet.Auswertung von (ersterWert TInf) fuhrt nicht zu einem geschlossenenTableau. Man sieht auch, dass es eine Moglichkeit in TInf) gibt, eine WHNFzu erhalten.Aber das Auswertung zu (ersterWert TInf2) fuhrt zu einem geschlossenenTableau.Die Ergebnisse bestatigen, dass ersterWert nicht den ganzen Eingabe-Baumauswertet, und auch die Erklarungen zu den abstrakten Werten TInf) und TInf2)

Beispiel 1.4.37 Zu Baumdatenstruktur.

psum xs = case xs of (Leaf a) -> a;

(Node k1 k2) -> (psum k1) + (psum k2)

Der Demand, der der Auswertung aller Elemente in den Blattern entspricht,ist die Menge der Baume, die ein Blatt mit ⊥-Element haben, und bei denenentsprechend die Zwischenknoten auch ⊥ sein konnen:Eine Analyse, ob ein Kombinator F alle Elemente eines Baumes auswertet,kann man mit

F TInf

durchfuhren, und den Tableaukalkul zur abstrakten Reduktion darauf anwenden.Fur psum sieht das so aus:

Analyse durch Fallunterscheidung uber TInf :psum TInf =⇒

• psum ⊥ → ⊥.

• psum (Leaf ⊥)→ ⊥

• psum (Node TInf >)→ psum TInf + psum>Unterausdruck an strikter Position kommt als Vorganger vor!

• psum (Node > TInf )→ psum>+ psum TInfUnterausdruck an strikter Position kommt als Vorganger vor!

Literaturverzeichnis

[MS99] A. K. D. Moran and D. Sands. Improvement in a lazy context: Anoperational theory for call-by-need. In POPL 1999, pages 43–56. ACMPress, 1999.

[Noc90] Eric Nocker. Strictness analysis using abstract reduction. TechnicalReport 90-14, Department of Computer Science, University of Nijme-gen, 1990.

[Pap00] Dirk Pape. Striktheitsanalysen funktionaler Sprachen. PhD thesis,Fachbereich Mathematik und Informatik, Freie Universitat Berlin,2000. in German.

[San98] David Sands. improvement theory and its applications, pages 275–306.Cambridge university press, 1998.

[Sch00] Marko Schutz. Analysing demand in nonstrict functionalprogramming languages. Dissertation, J.W.Goethe-UniversitatFrankfurt, 2000. available at http://www.ki.informatik.uni-frankfurt.de/papers/marko.

[SSSS07] Manfred Schmidt-Schauß, David Sabel, and Marko Schutz. Deci-ding inclusion of set constants over infinite non-strict data structu-res. RAIRO-Theoretical Informatics and Applications, 41(2):225–241,July 2007.

[SSSS08] Manfred Schmidt-Schauß, Marko Schutz, and David Sabel. Safety ofNocker’s strictness analysis. J. Funct. Programming, 18(04):503–551,2008.

[Wad87] P. Wadler. Strictness analysis on non-flat domains, pages 266–275.Ellis Horwood, 1987.

50