Grundlagen der Programmierung 2 Operationale Semantikprg2/SS2007/...Semantik von Haskell ist...

32

Transcript of Grundlagen der Programmierung 2 Operationale Semantikprg2/SS2007/...Semantik von Haskell ist...

  • Grundlagen der Programmierung 2

    Operationale Semantik

    Prof. Dr. Manfred Schmidt-Schauÿ

    Künstliche Intelligenz und Softwaretechnologie

    15. Mai 2007

  • Semantik von Programmiersprachen

    Grundlagen der Programmierung 2 - 2 -

    Semantik = Bedeutung eines Programms (Programmtextes)

    ausgehend vom Syntaxbaum des Programms.

    Methoden der Semantik-Definition:

    Operationale Semantik

    Denotationale Semantik

    Transformations-Semantik

    axiomatische Semantik

  • Operationale Semantik

    Grundlagen der Programmierung 2 - 3 -

    Spezifikation von Wirkung und Ablauf:

    Zustand: Speicherbelegung als Datenstruktur oder . . .Pro Programmkonstrukt: Angabe des Zustandsübergangs

    Haskell: Zustand = AusdruckÜbergänge: = Reduktionen, d.h. Änderungen der Ausdrücke.

    Python: Zustand = UmgebungÜbergänge: = Veränderungen des Speicherinhalts.

    operationale Semantik = Spezifikation eines Interpreters

    Vorteil: Prinzipiell immer durchführbar

  • Denotationale Semantik

    Grundlagen der Programmierung 2 - 4 -

    Zuordnung: Programm 7→ Funktion

    Domain D: Menge der möglichen Funktionenund Objekte

    Pro Programmkonstrukt: rekursive Angabe der Konstruktion einer

    Funktion in D.

    Hürden: Mathematisches Vorwissen notwendigDomainkonstruktion kann schwierig seinMeist nur für kleines Fragment einer Programmiersprache

  • Transformations-Semantik

    Grundlagen der Programmierung 2 - 5 -

    Vorgehen zur Definition der Semantik eines Programms P ,

    wenn die Semantik bereits für eine Untermenge der Programme erklärt

    • Transformiere P → . . . → P ′• Nehme die Semantik von P ′.

    Verwendung:

    Semantik einer vollen Programmiersprache erklärt durch:• Semantik der Kernsprache• Transformation: volle Sprache −→ Kernsprache.

    Semantik von Haskell ist teilweise eine Transformationssemantik

    Vorteile: Vereinfacht Semantik-DefinitionAnalog zur Arbeitsweise von Compilern

  • Axiomatische Semantik

    Grundlagen der Programmierung 2 - 6 -

    Beschreibung der Programmkonstrukte und Eigenschaften von Pro-

    grammen mittels logischer Axiome

    Herleiten von Programmeigenschaften durch logisches Schließen

    Z.B. in Prädikatenlogik:

    Für alle Eingaben n von natürlichen Zahlen

    liefert quadrat n das Ergebnis n2. Als Formel:

    ∀n : quadrat(n) = n2

  • Axiomatische Semantik

    Grundlagen der Programmierung 2 - 7 -

    Hoare-Logik:

    {x > 2} x := x+1 {x > 3}

    Vorbedingung

    Programmbefehl

    Nachbedingung

  • Auswertung von einfachen Haskell-Programmen:

    Grundlagen der Programmierung 2 - 8 -

    Ziel: operationale Semantik von Haskell

    • formal saubere Definition der Auswertung

    • auch für Funktionen höherer Ordnung

    • Unabhängigkeit von Compilern

    • Unabhängigkeit vom Rechnertyp (Portabilität)

  • Einfache Haskell-Programme

    Grundlagen der Programmierung 2 - 9 -

    Definition: Basiswert ist entweder eine Zahl,ein Zeichen oder True,False.

    Einfache Haskell-Programme: dürfen benutzen:

    • Basiswerte und entsprechende vordefinierte Operatoren• Funktionsdefinitionen• if-then-else• Anwendung von Funktionen auf Argumente

  • Einfache Haskell-Programme (2)

    Grundlagen der Programmierung 2 - 10 -

    Definition:

    Ein (einfaches) Haskell-Programm besteht aus:• Menge von Funktionsdefinitionen; entsprechend obiger Beschränkungen• Ausdruck (main) vom Typ eines Basiswertes.

    Wert des Programms = Wert von main

    Beispiel

    quadrat x = x * x

    kubik x = x * x * x

    w = 2

    main = if w >= 0 then quadrat w else kubik w

  • Berechnung und Auswertung

    Grundlagen der Programmierung 2 - 11 -

    Prinzip der Berechnung für einfache Haskell-Programme

    Auswertung =Folge von Transformationen

    von main

    bis ein Basiswert erreicht ist

    main → t1 → t2 → . . . → tn → . . .

    Es gibt drei Fälle:1. Die Folge endet mit einem Basiswert2. Die Folge endet, aber nicht mit einem Basiswert3. Die Folge endet nicht

    Bei 2. und 3.: Wert undefiniert.

  • Auswertung

    Grundlagen der Programmierung 2 - 12 -

    Einfache Haskell-Programm haben drei verschiedene

    Arten von Auswertungsschritten

    1. Definitionseinsetzung (δ-Reduktion)

    2. Arithmetische Auswertung

    3. Auswertung von Fallunterscheidungen

  • Satz von Church und Rosser

    Grundlagen der Programmierung 2 - 13 -

    Satz (Church-Rosser 1) Sei P ein einfaches Haskell-Programm,

    R1, R2 zwei verschiedene Reduktionsfolgen für main

    mit jeweiligen Resultat-Basiswerten e1 bzw. e2

    dann sind diese Basiswerte gleich, d.h. e1 = e2

  • Werte von Programmen

    Grundlagen der Programmierung 2 - 14 -

    Definition: Sei P ein einfaches Haskell-Programm und

    main von numerischem oder Booleschem Typ.

    Der Wert des Programms P ist:

    e wenn es eine terminierende Reduktionsfolge, ausgehend

    von main gibt, die mit dem Basiswert e endet,

    ⊥ ( undefiniert ) wenn es keine mit einem Basiswert terminierende Reduk-tionsfolge ausgehend von main gibt.

    Aus dem Satz von Church-Rosser-1 folgt:

    Ein einfaches Haskell-Programm

    hat einen eindeutig definierten Wert

    unabhängig von der Art der Auswertung

  • Satz 2 von Church und Rosser

    Grundlagen der Programmierung 2 - 15 -

    SATZ (Church-Rosser-2) Sei P ein einfaches Haskell-Programm.

    Wenn es irgendeine Reduktionsfolge für main gibt,

    die mit einem Basiswert e terminiert,

    dann terminiert auch die normale Reihenfolge der Auswertung von main

    und liefert als Basiswert (Resultat) genau e.

    Die normale Reihenfolge ist ausreichend zur Auswertung

    Haskell benutzt normale Reihenfolge der Auswertung

  • Gegenbeispiel zu C.R. 2 bei applikativ

    Grundlagen der Programmierung 2 - 16 -

    Church-Rosser-2 gilt nicht für die applikative Reihenfolge:

    nt x = nt x

    proj x y = x

    main = proj 0 (nt 1)

    applikative Reihenfolge für main terminiert nicht:

    (nt 1) → (nt 1) → (nt 1) → . . . . . .Deshalb:

    proj 0 (nt 1) → proj 0 (nt 1) → . . . . . .

    Die normale Reihenfolge liefert sofort 0.

  • Programmtransformationen

    Grundlagen der Programmierung 2 - 17 -

    Optimierung: Programm P wird zur Compilezeit mittels

    Transformationen in ein anderes Programm P ′ umgewandelt,welches weniger Ressourcen benötigt, aber den gleichen Effekt hat.

    ”gleicher Effekt” (∼) :• ∼ ist mithilfe der operationalen Semantik definierbar• Äquivalenzrelation ∼ auf Programmen

    und Funktionen vom gleichen Typ• Verschiedene Zahlen und Boolesche Werte

    sind verschieden unter ∼.

  • Programmtransformationen

    Grundlagen der Programmierung 2 - 18 -

    Aussage:

    Für einfache Haskellprogramme gilt:

    Alle bisher betrachteten Reduktionen, auch deren Umkehrung, sind

    auch als Compilezeit-Transformationen verwendbar.

    D.h. Wenn P → P ′ mit einer Reduktion, dann gilt auch P ∼ P ′.

    Begründung: 1. Satz von Church-Rosser:

    Wenn P zu e auswertet und P → P ′ ist eine Transformation,dann wertet auch P ′ zu e aus.

  • Programmtransformationen

    Grundlagen der Programmierung 2 - 19 -

    Beispiel:[x]++xs

    → x:( [] ++ xs) Reduktion für append→ x:xs Transformation mittels append

    =⇒ [x]++xs kann zu x:xs vereinfacht werden

  • Programmtransformationen

    Grundlagen der Programmierung 2 - 20 -

    Bei applikativer Reihenfolge der Auswertung

    sind diese Transformationen nicht korrekt,

    sowie in Programmiersprachen, die appl. Reihenfolge verwenden.

    Ein terminierendes Programm kann zu einem nichtterminierenden wer-

    den:

    meinif b x y = if b then x else y

    main = meinf True True bot

    Nach der Transformation:

    main = if True then True else bot

    D.h. auch: ein nichtterminierendes Programm kann zu einem terminie-

    renden werden.

  • Church-Rosser-Sätze auch für Konstruktoren

    Grundlagen der Programmierung 2 - 21 -

    Verallgemeinerter Wert statt Basiswert; auch Listen sind Werte:

    Ein (verallgemeinerter) Wert ist entweder1. ein Basiswert d.h. eine Zahl oder einer der

    Wahrheitswerte True, False,

    oder2. eine Applikation (c t1 . . . tn), wobei c ein Konstruktor ist

    mit der Stelligkeit n

    Beispiele: [1,2,3,4]1: (map quadrat [2,3,4])

    Beachte: verallgemeinerte Werte können unausgewertete Unteraus-

    drücke haben

  • Church-Rosser-Sätze für Haskell-Programmemit Listen

    Grundlagen der Programmierung 2 - 22 -

    Satz(Church-Rosser-1) Sei P ein Haskell-Programm,wobei Konstruktoren und case erlaubt sind, undmain den Typ eines verallgemeinerten Basiswertes hat.

    Wenn zwei verschiedene Reduktionsfolgen jeweilsverallgemeinerte Werte e1 bzw. e2 ergeben,dann gibt es einen weiteren verallgemeinerten Wert e3,so dass sowohl e1 als auch e2 zu e3 (in keinem, einem oder mehrerenSchritten) reduziert werden können:

    P

    ~~||||

    ||||

    ||||

    ||||

    |

    BBB

    BBBB

    BBBB

    BBBB

    BB

    e1

    !!BB

    BB

    BB

    BB

    Be2

    }}||

    ||

    ||

    ||

    |

    e3

  • Church-Rosser-Sätze; Beispiele

    Grundlagen der Programmierung 2 - 23 -

    Beispiel: Der Ausdruck [3+4,5+6] ist schon ein Wert,auf zwei Arten reduzierbar:

    [3 + 4,5 + 6]

    wwnnnnnn

    nnnnnn

    nnnnnn

    nnnnnn

    nnn

    ((PPPPP

    PPPPPP

    PPPPPP

    PPPPPP

    PPPPP

    [7,5 + 6]

    ''PPP

    PPPP

    PPPP

    PPP

    [3 + 4,11]

    vvn nn n

    n nn n

    n nn n

    n n

    [7,11]

  • Church-Rosser-Sätze; Beispiele

    Grundlagen der Programmierung 2 - 24 -

    Beachte: Normalform muss nicht existieren

    Beispiel

    (3 + 4) : ((5 + 6) : [1..]

    ttiiiiiiii

    iiiiiiii

    iiiiiiii

    iiiiiiii

    iiiiiii

    **UUUUUUU

    UUUUUUUU

    UUUUUUUU

    UUUUUUUU

    UUUUUUUU

    U

    7 : ((5 + 6) : [1..]

    **UUUUUUU

    UUUUUUUU

    UUUUUUUU

    UUUUUUUU

    UUUUUUUU

    (3 + 4) : (11 : [1..])

    ttiiiiiiii

    iiiiiiii

    iiiiiiii

    iiiiiiii

    iiiiiiii

    7 : 11 : [1..]

  • Church-Rosser-Satz 2

    Grundlagen der Programmierung 2 - 25 -

    Satz (Church-Rosser-2) Sei P ein let-freies Haskell-Programm.

    Wenn irgendeine Reduktionsfolge main zu einem verallg. Wert e redu-

    ziert,

    dann terminiert auch die normale Reihenfolge der Auswertung von main

    mit einem verallg. Wert e1,

    und e1 ist reduzierbar zu e.

    P

    e

    e

    1

    Ex: n

    orma

    le Au

    sw.

    v. Wert

  • Church-Rosser-Satz 2. Beispiel

    Grundlagen der Programmierung 2 - 26 -

    [3+4]++[5+6]

    [3+4,5+6]

    [3+4,11]

    norm

    ale A

    usw.

  • Haskell mit rekursivem let

    Grundlagen der Programmierung 2 - 27 -

    Church-Rosser-Sätze gelten nicht in vollem Haskell

    Grund: rekursives let.

    Church-Rosser-Sätze sind zu syntaktisch

  • Church-Rosser-Sätze: Verallgemeinerung

    Grundlagen der Programmierung 2 - 28 -

    Notwendig: Konzept der Verhaltensgleichheit ∼ von Ausdrücken:

    • verschiedene Basiswerte a, b sind nicht verhaltensgleich:a 6= b ⇒ a 6∼ b

    • man kann Gleiches durch Gleiches ersetzena ∼ b ⇒ P [a] ∼ P [b]

    Nachzuweisen ist dann:• Reduktion erhält Verhaltensgleichheit:

    s → t ⇒ s ∼ t

  • Induktion und Co-Induktion zum Nachweis derGleichheit von Ausdrücken

    Grundlagen der Programmierung 2 - 29 -

    Induktionsschema für endliche Listen xs:

    1. Zeige die Behauptung für xs = [].2. Zeige, dass die Behauptung für x : xs gilt

    unter der Annahme, dass sie für xs gilt.

  • Co-Induktion für Listen

    Grundlagen der Programmierung 2 - 30 -

    Co-Induktionsschema für endliche und unendliche Listen xs:

    1. Zeige die Behauptung für xs = [].2. Zeige die Behauptung für xs = ⊥.3. Zeige, dass die Behauptung für x : xs gilt

    unter der Annahme, dass sie für xs gilt.

  • Induktion für endliche Listen. Beispiel

    Grundlagen der Programmierung 2 - 31 -

    Zeige: length(xs ++ ys) = length(xs) + length(ys)für alle endlichen Listen xs,ys

    Basisfall:

    length([] ++ ys ) = length(ys),

    und length([]) + length(ys) = length(ys)

  • Induktion. Beispiel

    Grundlagen der Programmierung 2 - 32 -

    Zeige: length(xs ++ ys) = length(xs) + length(ys)für alle endlichen Listen xs,ys

    Induktionsfall: xs ist eine Liste der Länge n + 1.

    Auswertung beider Seiten, wobei xs = x:xs’.

    length(xs ++ ys) → length((x:xs’ ++ ys)→ length((x:(xs’ ++ ys)) →1+ length((xs’ ++ ys)) = 1+ length(xs’)+ length(ys)).

    length(xs) + length(ys) = length(x:xs’) + length(ys) →1+ length(xs’) + length(ys).