Technische Universität München
Grundlagen der Programm- und Systementwicklung
Funktionale Programmierung
Teil 2 Methodik:
Spezifikation, Implementierung, Verifikation
Technische Universität München
Institut für Informatik
Software Engineering
Vortragender: Prof. Dr. Alexander Pretschner
Übung: Dipl.-Inf. Florian Kelbert, Dr. Alexander Malkis
Folien: Prof. Dr. Dr. h.c. Manfred Broy, Dr. Alexander Malkis,
Prof. Dr. Alexander Pretschner, Dr. Maria Spichkova, …
1
Technische Universität München
Vorlesungsplanung (siehe Webseite)
Einführung
Grundbegriffe und Definitionen, Bedeutung und Stellenwert Kernaufgaben,
Aktueller Stand der Forschung und Praxis
Themen
Daten und Rechenstrukturen
Konzepte
Spezifikation
Verifikation von Eigenschaften
Funktionale Programme
Konzepte
Spezifikation
Verifikation von Eigenschaften
Anweisungs- und objektorientierte Programme
Spezifikation
Verifikation von Eigenschaften
Referenzen und Zeiger
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
2
Technische Universität München
Methodik funktionaler Programmierung
Spezifikation
Entwurf und Implementierung
Verifikation
Partielle Korrektheit
Terminierung
Konzepte funktionaler Programmierung
Funktionen höherer Ordnung
Currying
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
3
Technische Universität München
Spezifikation funktionaler Programme
Funktionale Programme bestehen aus einer Familie rekursiver Deklarationen
von Funktionen.
Die Spezifikation eines funktionalen Programms entspricht somit
der Angabe der Funktionalität/Sorten und
der Charakterisierung dieser Familie von Funktionen durch logische Eigenschaften.
Algebraische Spezifikation einer Funktion f:
die Funktionalität von f (ihre Funktionssorte),
eine Anzahl von Gleichungsaxiomen und ggf. Definiertheitsaxiome
Prädikative Spezifikation einer Funktion f:
Funktionen werden durch ihre charakteristischen Eigenschaften beschrieben,
nicht nur Gleichungen sondern allgemeine (auch nichtmonotone) Prädikate,
es wird ein beliebiger prädikatenlogischer Ausdruck für die Spezifikation verwendet,
ein verbreitetes Format: zwei Prädikate – „Vor- und Nachbedingung“ –
Assumption/Commitment
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
4
Technische Universität München
Mustersuche in einem Text
Gesucht ist Funktion
search: Seq Char, Seq Char Nat ,
die eine Position des Musters
m : Seq Char
(wenn vorhanden) im Text
x : Seq Char
liefert, d.h. mit
( i Nat: found(x, i, m) = true) ⇒ found(x, search(x, m), m) = true ,
wobei
found: Seq Char, Nat, Seq Char Bool
found(x, n, m) = true ⇔ ( s, r Seq Char: x = s∘m∘r n = #s) .
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
5
Technische Universität München
Mustersuche in einem binären gewurzelten Baum
Gesucht ist Funktion
search: Tree Char, Tree Char Seq Bool
die eine Position des Musters
m : Tree Char
(wenn vorhanden) im Baum
x : Tree Char
liefert, d.h. mit
( p Seq Bool: found(x, p, m) = true) found(x, search(x, m), m) = true ,
wobei
found: Tree Char, Seq Bool, Tree Char Bool
found(x, ‹›, m) = true ⇔ x = m
found(etree, ‹b› p, m) = false
found(x, ‹false› p, m) = found(left(x), p, m)
found(x, ‹true› p, m) = found(right(x), p, m)
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
6
Technische Universität München
Erreichbarkeit in Graphen
Gegeben:
Graph durch Funktion
g: Node Fset Node
liefert zu jedem Knoten n die Menge g(n) der durch eine Kante
erreichbaren Knoten
Gesucht: Funktion
reach: Node Fset Node
die zu jedem Knoten n die Menge reach(n) der in g durch eine Folge von
Kanten (einen „Pfad“) erreichbaren Knoten liefert.
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
7
Technische Universität München
Prädikative Spezifikation
m reach(n) = s Seq Node: ispath(n, s, m)
wobei
ispath : Node, Seq Node, Node Bool
durch die folgende algebraische Spezifikation beschrieben wird:
ispath(n, ‹›, m) = true ⇔ n=m
ispath(n, ‹a› ∘ s, m) = and(isel(g(n), a) , ispath(a, s, m))
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
8
Technische Universität München
Spezifikation vs. funktionales Programm
Für ein Funktionssymbol f mit Funktionalität
f : M1 , ... , Mn Mn+1
und ein spezifizierendes Prädikat (Spezifikation einer Funktion)
R: (M1 , ... , Mn Mn+1) IB
formulieren wir die Aussage, dass f die Spezifikation R erfüllt:
f sat R
(oder auch R(f))
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
9
Technische Universität München
Assumption/Commitment - Spezifikation
Für ein Funktionssymbol f : M1 , ... , Mn Mn+1
erhalten wir eine Spezifikation
assume(x1 , ... , xn) = true commit(x1 , ... , xn, f(x1 , ... , xn)) = true
beschrieben durch die Prädikate
assume : M1 , ... , Mn Bool und commit : M1 , ... , Mn, Mn+1 Bool
Beispiel:
insort: Seq Nat, Seq Nat → Seq Nat
is_sorted(s) = true and(is_sorted(insort(r, s)), insort(r, s) ros) = true
mit
is_sorted: Seq Nat Bool
Sequenz ist sortiert
_ _: Seq Nat, Seq Nat Bool
Sequenzen haben gleiche Elemente
Das Assume-Prädikat ist (r: Seq Nat, s: Seq Nat) Bool: is_sorted(s) .
Das Commit-Prädikat ist
(r: Seq Nat, s: Seq Nat, f: (Seq Nat, Seq Nat → Seq Nat)) Bool:
and(is_sorted(f(r, s)), f(r, s) ~ ros) .
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
10
Technische Universität München
BEWEISEN VON EIGENSCHAFTEN FÜR
FUNKTIONALE PROGRAMME
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
11
Technische Universität München
Deklaration – Aussagen
Gegeben rekursive Deklaration
fct f = (x1 : M1, ..., xn : Mn)Mn+1 : t
Für f gilt die Gleichung:
f(x1, ..., xn) = t
Weiter gilt: f ist die am wenigsten definierte Funktion, die die Gleichung
erfüllt:
( x1, ..., xn : g(x1, ..., xn) = t[g/f] ) f ⊑ g
Wenn wir Aussagen über f beweisen wollen, können wir uns auf diese
Eigenschaft stützen.
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
12
Technische Universität München
Beweisprinzipien für Rekursion
Berechnungsinduktion
Beweise durch Fixpunkteigenschaften
Strukturelle Induktion
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
13
Technische Universität München
Beweisprinzipien für Rekursion: Berechnungsinduktion
Die Berechnungsinduktion:
erlaubt induktive Beweise von Eigenschaften für rekursiv deklarierte
Funktionen, falls das auftretende Funktional stetig ist.
das zu beweisende Prädikat muss gewisse Eigenschaften haben.
Zulässigkeit des Prädikates.
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
14
Technische Universität München
Beweisprinzipien für Rekursion: Berechnungsinduktion
Sei (X,⊑) eine vollständige Halbordnung. Ein Prädikat
φ: X → IB
heißt zulässig (engl. admissible), falls für jede gerichtete
Menge N⊆X gilt:
(∀ a∈N: φ(a)) ⇒ φ(sup N) .
Beachte:
Unsere Definition der Vollständigkeit für Halbordnungen fordert die
Existenz von Suprema für alle gerichtete Mengen, insbesondere für die
leere Menge. Ist also ⊥∈X das kleinste Element einer vollständigen
Halbordnung, so gilt φ(⊥) für jedes zulässige Prädikat φ auf X.
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
15
Technische Universität München
Beispiele: ein zulässiges und ein unzulässiges Prädikat
Ist (X,⊑) eine vollständige Halbordnung und g ∊ X, so ist
φ: X→𝔹, f ↦ (f⊑g) ein zulässiges Prädikat auf X.
Beweis:
Sei N⊆X gerichtet mit ∀ f∊N: φ(f). Dann gilt ∀ f∊N: f⊑g, also sup⊑(N) ⊑ g.
Sei ℕ⊥ mit flacher Halbordnung ≼ versehen, und sei ℕ⊥→ℕ⊥
punktweise partiell geordnet:
f ⊑ g gdw. ∀ x∊ℕ⊥: f(x) ≼ g(x) (f,g ∈ ℕ⊥→ℕ⊥).
Dann ist (ℕ⊥→ℕ⊥, ⊑) eine vollständige Halbordnung und
φ: (ℕ⊥→ℕ⊥)→𝔹, f ↦ (idℕ⊥⋢f) ein nicht zulässiges Prädikat.
Beweis:
(ℕ⊥→ℕ⊥, ⊑) vollständige Halbordnung: ist F ⊆ (ℕ⊥→ℕ⊥) gerichtet, so ist
λ x∊ℕ⊥. sup≼{f(x) | f ∊ F} wohldefiniert und gleich sup⊑(F).
φ nicht zulässig:
N = { f: ℕ⊥→ℕ⊥ | f(⊥)=⊥ ∧ ∃ n∈ℕ: ((∀ x<n: f(x)=x) ∧ (∀ x≥n: f(x)=⊥)) }
ist gerichtet, idℕ⊥⋢ f gilt für alle f ∊ N, aber sup⊑(N) = idℕ⊥.
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
16
Technische Universität München
Beweisprinzipien für Rekursion: Berechnungsinduktion
Hierbei ist fix τ der kleinste Fixpunkt von τ.
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
17
Technische Universität München
Beweise durch Fixpunkteigenschaften
Aus den Fixpunkteigenschaften lassen sich Eigenschaften für eine
rekursiv deklarierte Funktion f beweisen.
Dies funktioniert aber nur für Eigenschaften, die für alle Fixpunkte
gelten.
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
18
Technische Universität München
Beweise durch Fixpunkteigenschaften
Fixpunkt von τ ist.
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
19
Technische Universität München
Beweise durch Fixpunkteigenschaften
Um τ(g)=g zu zeigen, zeigen wir per Induktion über a, dass
∀a,b ∈ Nat: (τ(g))(a,b) = g(a,b) :
Für alle a,b ∈ Nat gilt:
(τ(g))(a,b)
= if a=0 then b else g(a-1, a*b) fi
= if a=0 then b else (a-1)!*a*b fi
= if a=0 then b else a!*b fi
= a!*b
= g(a,b) .
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
20
Technische Universität München
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
21
Technische Universität München
Beweisprinzipien für Rekursion: Strukturelle Induktion
Schließlich können wir Beweise über rekursiv definierte Funktionen
auch führen, indem wir klassische Beweisprinzipien der Induktion
bezüglich der Argumentbereiche zusammen mit der
Fixpunkteigenschaft verwenden.
Dies erfordert eine Noethersche Ordnung auf dem Definitionsbereich.
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
22
Technische Universität München
Beweisprinzipien für Rekursion: Induktion
… indem wir lediglich ausnutzen, dass reverse die folgende Gleichung erfüllt:
τ(reverse) = reverse für das dazugehörige Funktional τ,
sprich,
(λx. if iseseq(x) then x elif iseseq(rest(x)) then x else reverse(rest(x))o〈first(x)〉 fi)
= reverse ,
oder äquivalent
∀ x: ((if iseseq(x) then x elif iseseq(rest(x)) then x else reverse(rest(x))o〈first(x)〉 fi)
= reverse(x)).
Wir werden hier nicht ausnutzen, dass reverse die kleinste Lösung der Gleichung ist (in der Tat
gibt es keine größere).
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
23
Technische Universität München
Beispiel: Induktion über ℕ
Lemma: ∀ s,t ∈ Seq α : reverse(s∘t) = reverse(t)∘reverse(s).
Beweis: Durch Induktion über die Länge von s.
Sei s ∈ Seq α beliebig, fest. Wir nehmen an, dass
∀ s’ ∈ Seq α : |s’|<|s| ⇒ ∀ t ∈ Seq α : reverse(s’∘t) = reverse(t)∘reverse(s’)
und zeigen ∀ t ∈ Seq α : reverse(s∘t) = reverse(t)∘reverse(s).
Sei t ∈ Seq α beliebig, fest.
Falls s=ε, so reverse(s∘t) = reverse(t) = reverse(t)∘ε = reverse(t)∘reverse(s).
Falls s=〈a〉 und t=ε, so reverse(s∘t) = reverse(〈a〉) = reverse(s)∘reverse(t).
Falls s=〈a〉 und t≠ε, so reverse(s∘t) = reverse(〈a〉∘t) [Def. von reverse]
= reverse(t)∘〈a〉 = reverse(t)∘reverse(s).
Falls ε≠s≠〈a〉, so reverse(s∘t) [Axiome über first, rest]
= reverse((〈first(s)〉∘rest(s))∘t) [Assoziativität]
= reverse(〈first(s)〉∘(rest(s)∘t)) [Def. von reverse]
= reverse(rest(s)∘t)∘〈first(s)〉 [Induktions-Annahme]
= (reverse(t)∘reverse(rest(s)))∘〈first(s)〉 [Assoziativität]
= reverse(t)∘(reverse(rest(s))∘〈first(s)〉) [Def. von reverse]
= reverse(t)∘reverse(〈first(s)〉∘rest(s)) [Axiome über first, rest]
= reverse(t)∘reverse(s).
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
24
Technische Universität München
Beispiel: strukturelle Induktion
Satz: ∀ s ∈ Seq α : reverse(reverse(s)) = s.
Beweis: Durch Induktion über die Teilzeichenkette-Relation.
Sei s ∈ Seq α beliebig, fest. Wir nehmen an, dass
∀ r ∈ Seq α : r echte Teilzeichenkette von s ⇒ reverse(reverse(r)) = r.
und zeigen reverse(reverse(s)) = s.
Falls s=ε, so reverse(reverse(s)) = reverse(reverse(ε)) = reverse(ε)
= ε = s.
Falls s=〈a〉, so reverse(reverse(s)) [Def. von reverse]
= reverse(〈a〉) = 〈a〉.
Falls ε≠s≠〈a〉, so reverse(reverse(s)) [Axiome über first, rest]
= reverse(reverse((〈first(s)〉∘rest(s))) [Def. von reverse]
= reverse(reverse(rest(s))∘〈first(s)〉) [Lemma]
= reverse(〈first(s)〉)∘reverse(reverse(rest(s))) [Def. von reverse]
= 〈first(s)〉∘reverse(reverse(rest(s))) [Induktions-Annahme]
= 〈first(s)〉∘rest(s) [Axiome über first, rest]
= s.
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
25
Technische Universität München
Terminierungsbeweise
Abstiegsfunktion (Bewertungsfunktion)
Beweis: Schema
Beispiele
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
26
Technische Universität München
Terminierungsbeweise
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
27
Technische Universität München
Terminierungsbeweise
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
28
Technische Universität München
Terminierungsbeweise
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
29
Technische Universität München
Terminierungsbeweis: Beispiel
Sei p(x,y) = (x=0 ∨ y>0).
(Streng genommen or(iszero(x) , not(iszero(y))) .)
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
30
Technische Universität München
Terminierungsbeweis: Beispiel
Seien feste x,y ∈ Nat mit p(x,y) gewählt, d.h. x=0 ∨ y>0.
Wir nehmen an, dass für alle (x’,y’) mit p(x’,y’) und h(x’,y’)<h(x,y)
die Formel Def[f(x’,y’)] gilt. Wir zeigen, dass Def[f(x,y)] gilt.
• Induktionsanfang (Fall h(x,y)=0):
Wegen h(x,y)=0 gilt x≤y. Dann ist
Funktionsrumpf[Ω/f] = if x≤y then y else Ω(x,2*y) fi = y
definiert.
• Induktionsschritt (Fall h(x,y)>0):
Wegen h(x,y)>0 ist if x≤y then 0 else x-y fi > 0, also h(x,y) =
x-y und x>y. Dann x≠0. Wegen p(x,y) muss also y>0 gelten.
Daher ist 2*y>y und x-2*y < x-y, daher
h(x,2*y) ≤ x-2*y < h(x,y). Nach Induktionsannahme gilt
Def[f(x,2*y)]. Dann gilt auch
Def[if x≤y then y else f(x,2*y) fi].
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
31
Technische Universität München
Funktionale Sorten
Gewünscht: in Programmen (und ihren Spezifikationen) Funktionen
als Parameter zulassen.
Bsp.: Ordnungsrelation für Sortieroperation, Prädikate für Filtrierung
einer Liste, beliebige Operation für foldl-Funktion auf Listen.
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
32
Technische Universität München
Funktionale Sorten: Beispiel
1. Stufe:
2. Stufe:
2. Stufe:
3. Stufe:
f1: Nat → Nat
f2: (Nat → Nat), Nat → Nat
f3: Nat → (Nat → Nat)
f4: ((Nat → Nat), Nat → Nat), Nat → (Nat → Nat)
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
33
Technische Universität München
Funktionsabstraktion - Motivation
Gewünscht:
- trivialen Funktionen keinen Namen geben.
- Funktionen im Kontext bereits gebundener Variablen definieren.
Beispiel aus Scheme:
(filter (lambda (x) (equal? x 1)) '(1 2 3))
=> (1) .
Beispiel aus Haskell:
Prelude> foldl (\x y -> concat ["(",x,"+",y,")"]) "0" (map show [1..13])
"(((((((((((((0+1)+2)+3)+4)+5)+6)+7)+8)+9)+10)+11)+12)+13)" .
Beispiel aus OCaml:
(let one = 1 in List.sort (fun x y -> if (one*x)>y then 1 else 0)) [5;3;7;1];;
liefert
- : int list = [1; 3; 5; 7] .
Wir formalisieren namenlose Funktionen wie folgt.
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
34
Technische Universität München
Funktionsabstraktion - Definition
Eine Funktionsabstraktion ist ein Term
(x1: M1, …, xn: Mn) Mn+1 : t ,
wobei
M1, …, Mn+1 Sorten sind,
falls jedes xi im Term t die Sorte Mi hat (1≤i≤n),
so hat t die Sorte Mn+1.
Die freien Identifikatoren (freien Variablen) der Funktionsabstraktion wie oben
sind die freien Variablen von t ohne x1, …, xn.
Beispiel:
Sei fct f2 = (g: (Nat)Nat, z: Nat) Nat : g(z)+z .
Der Term f2((x: Nat)Nat: x+succ(0), succ(0))
= ((g: (Nat)Nat, z: Nat) Nat : g(z)+z) ((x: Nat)Nat: x+succ(0), succ(0))
kann zu ((x: Nat)Nat: x+succ(0)) (succ(0))+succ(0) und dann zu
(succ(0)+succ(0))+succ(0) reduziert werden. Über ℕ ist die Interpretation des
letzten Terms gleich 3.
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
35
Technische Universität München
Currying
Gewünscht:
- In der Theorie: ohne Tupel-Schreibweise auskommen.
- In der Praxis: partielle Evaluation von Termen wie f(3,5,x).
Lösung:
Funktion curryi (sei i ℕ, 1 i n)
Benannt nach dem Logiker Haskell Curry (1900-1982),
gleichzeitig Namenspatron für die funktionale
Programmiersprache Haskell.
Statt curry1 schreiben wir curry.
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
36
Technische Universität München
Currying: Beispiel
Sei
add: Nat, Nat → Nat
mit Interpretation der Addition über ℕ.
Dann ist
curry(add): Nat → Nat → Nat
mit
curry(add)(n) = (m: Nat) Nat: add(n,m) .
Die Interpretation des Terms
curry(add)(succ(succ(succ(succ(succ(0))))))
über ℕ ist die Funktion, die zu jedem Argument 5
hinzuzählt.
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
37
Technische Universität München
Funktionskomposition und Formale Parameter
Relationale Komposition f ∘ g zweier Funktionen f, g mit
f: M1 M2
g: M2 M3
ist eine polymorphe Funktion höherer Stufe mit Funktionssorte
f ∘ g : (1 2), (2 3) (1 3)
Es gilt:
(f ∘ g)(x) = g(f(x))
Gebundene vs. freie Bezeichnungen: Beispiel
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
38
Technische Universität München
Tupel
Gewünscht:
- (Theorie) in einigen Fällen statt viele Funktionen großer Stelligkeit nur eine
Funktion beliebiger Stelligkeit und die restlichen Funktionen einstellig haben.
- oder (Praxis) einen Satz von Argumenten als eine Einheit betrachten.
Lösung: Tupelsorten [M1, ..., Mn], ähnlich zu Produktsorten und Records.
Tupelbildende Funktion [ _, ..., _ ] : M1, ..., Mn [M1, ..., Mn]
Strikte Tupelbildung
Tupelbildende Funktion wird als strikt angenommen.
Tupel enthalten dann niemals das Pseudoelement als Eintrag.
Mengenprodukt als Trägermenge für die Tupelsorte [M1, ..., Mn] :
((M1 \ {}) ... (Mn \ {}) ) {}
Nichtstrikte Tupelbildung
Tupelbildende Funktion wird als nichtstrikt angenommen.
Mengenprodukt als Trägermenge für die Tupelsorte [M1, ..., Mn] :
(M1 ... Mn) \ {(,..., )} {}
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
39
Technische Universität München
Zwei schwächere Formen der Erfüllung einer Spezifikation
Eine Funktion f ist partiell korrekt bezüglich der Spezifikation R:
f satpar R
g: f ⊑ g R(g)
f liefert Resultate, wie in der Spezifikation gefordert, falls sie terminiert.
Die Terminierung von f ist jedoch nicht garantiert, selbst wenn sie in der
Spezifikation R gefordert wird.
Eine Funktion f ist robust korrekt bezüglich der Spezifikation R:
f satrob R
g: g ⊑ f R(g)
f terminiert für alle Fälle, die durch die Spezifikation gefordert werden
f liefert dann Werte wie spezifiziert.
Sogar in Fällen, in denen die Spezifikation keine Terminierung fordert und keine
Werte vorschreibt, kann f terminieren (und beliebig gewählte Werte liefern).
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
40
Technische Universität München
Partielle und robuste Korrektheit: Beispiele
fct div1 = (x,y: Nat) Nat: if x<y then 0 else div1(x-y, y)+1 fi
fct div2 = (x,y: Nat) Nat: if y=0 ∨ x<y then 0 else div2(x-y, y)+1 fi
fct div3 = (x,y: Nat) Nat: if x<y then 0 else div3(x-2*y, y)+2 fi
(mit ∀ x,y∈ Nat : x<2*y ⇒ x-2*y=⊥)
R(f)
=
∀ x,y∈ Nat: ( ( y>0 ⇒ y*f(x,y) ≤ x < y*(f(x,y)+1) )
∧ ( y=0 ⇒ f(x,y) = ⊥) )
div1 sat R, da R(div1).
div2 satrob R, da div1⊑div2 ∧ R(div1).
div3 satpar R, da div3⊑div1 ∧ R(div1).
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
41
Technische Universität München
Abschließende Bemerkungen
Funktionale Programmierung
Vorteile
wenige einfache transparente Konzepte
klare Semantik
hohe Unabhängigkeit von technischen Details
hohe Modularität
Nachteile
Heutige Maschinen arbeiten nach dem von Neumann-Konzept
(Prozessor/Speicher/Instruktion)
Hohe Effizienz auf heute gängigen Maschinen nicht vollständig erreichbar
Pretschner WS 14/15 Grundlagen der Programm- und Systementwicklung: Funktionale Programmierung:
Methodik
42