Top Banner
Deklarative Programmierung Prof. Dr. Sibylle Schwarz HTWK Leipzig, Fakultät IMN Gustav-Freytag-Str. 42a, 04277 Leipzig Zimmer Z 411 (Zuse-Bau) http://www.imn.htwk-leipzig.de/~schwarz [email protected] Sommersemester 2015
162

Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Aug 16, 2019

Download

Documents

vuquynh
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Deklarative Programmierung

Prof. Dr. Sibylle SchwarzHTWK Leipzig, Fakultät IMN

Gustav-Freytag-Str. 42a, 04277 LeipzigZimmer Z 411 (Zuse-Bau)

http://www.imn.htwk-leipzig.de/[email protected]

Sommersemester 2015

Page 2: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Motivation

. . . there are two ways of constructing a software design:One way is to make itso simple that there are obviously no deficienciesand the other way is to make itso complicated that there are no obvious deficiencies.The first method is far more difficult.

Tony Hoare, 1980 ACM Turing Award Lecture

Page 3: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Programmierparadigmen

Abstraktionsstufen (zeitliche Entwicklung):I Programm = MaschinencodeI menschenlesbare symbolische Darstellung (Assembler)I Beschreibung von Programmablauf- und Datenstrukturen

(imperative und objektorientierte Sprachen)I Beschreibung der Aufgabenstellung

(deklarative Sprachen, z.B. funktional, logisch, Constraints)

Unterschied besteht darin, wie detailliert das Programm dasLösungsverfahren beschreiben muss.

Page 4: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Formen der deklarativen ProgrammierungGrundidee:Jedes Programm ist ein mathematisches Objekt mit einer bekanntenwohldefinierten Semantikfunktionale Programmierung (z.B. Haskell, ML, Lisp):

Programm: Menge von Funktions-Definitionen(Gleichungen zwischen Termen)

Ausführung: Pattern matching, Reduktion (Termersetzung)logische Programmierung (Prolog):

Programm: Menge logischer Formeln (Horn-Klauseln)Ausführung: Unifikation, SLD-Resolution

funktional-logische Programmierung (z.B. Mercury, Curry):Kombination funktionaler und logischer Konzepte

Constraint-Programmierung:Programm: Menge von Constraints

(z.B. Gleichungen, Ungleichungen, logische Formeln)Ausführung: Constraint-Löser (abhängig vom Constraint-Bereich)Beispiele: Constraints: Menge linearer Gleichungen

Constraint-Löser: Gauß-AlgorithmusConstraints: aussagenlogische CNFConstraint-Löser: SAT-Solver

Page 5: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Beispiele

I funktionale Programmierung: foldr (+) 0 [1,2,3]

foldr f z l = case l of[] -> z ; (x:xs) -> f x (foldr f z xs)

I logische Programmierung: append(A,B,[1,2,3]).append([],YS,YS).append([X|XS],YS,[X|ZS]):-append(XS,YS,ZS).

I Constraint-Programmierung(set-logic QF_LIA) (set-option :produce-models true)(declare-fun a () Int) (declare-fun b () Int)(assert (and (>= a 5) (<= b 30) (= (+ a b) 20)))(check-sat) (get-value (a b))

Page 6: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Deklarative vs. imperative Programmierungdeklarativ (beschreibend)

Programm: Repräsentation einer AufgabeProgrammelemente: Ausdrücke (Terme),

Formeln, GleichungenProgrammierung: Modellierung der AufgabeAusführung: Lösung des beschriebenen Problems

durch Standardverfahren z.B.logisches Schließen,Umformung von Ausdrücken

imperativ zustandsorientiert (von-Neumann-Typ)Programm: Repräsentation eines AlgorithmusProgrammelemente: Ausdrücke und AnweisungenProgrammierung: Modellierung eines Verfahrens

zur Lösung einer AufgabeAusführung des Lösungsverfahrens durch

schrittweise Zustandsänderungen(Speicherbelegung)

Page 7: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Definition

deklarativ: jedes (Teil-)Programm/Ausdruck hat einen Wert

. . . und keine weitere (versteckte) Wirkung.

Werte können sein:I „klassische“ Daten (Zahlen, Listen, Bäume. . . )I Funktionen (Sinus, . . . )I Aktionen (Datei schreiben, . . . )

Page 8: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Softwaretechnische Vorteile

der deklarativen Programmierung:

Beweisbarkeit : Rechnen mit Programmen wie in derMathematik mit Termen

Sicherheit : es gibt keine Nebenwirkungenund Wirkungen sieht man bereits am Typ

Wiederverwendbarkeit : durch Entwurfsmuster(= Funktionen höherer Ordnung)

Effizienz : durch Programmtransformationen im CompilerParallelisierbarkeit : durch Nebenwirkungsfreiheit

Page 9: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Beispiel Spezifikation/Test

import Test.SmallCheck

append :: [t] -> [t] -> [t]append x y = case x of

[] -> yh : t -> h : append t y

associative f =\ x y z -> f x (f y z) == f (f x y) z

test1 = smallCheck(associative (append::[Int]->[Int]->[Int]))

Übung: Kommutativität (formulieren und testen)

Page 10: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Beispiel Verifikation

app :: [t] -> [t] -> [t]app x y = case x of

[] -> yh : t -> h : app t y

zu beweisen:

app x (app y z) == app (app x y) z

Beweismethode: Induktion nach x.I Induktionsanfang: x == [] . . .I Induktionsschritt: x == h : t . . .

Page 11: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Deklarative Programmierung in der Lehre

funktionale Programmierung: diese Vorlesunglogische Programmierung: in LV Künstliche Intelligenz

Constraint -Programmierung: als Master-Wahlfach

Beziehungen zu weiteren LV: VoraussetzungenI Bäume, Terme (Alg.+DS, TGI)I Logik (TGI, Digitaltechnik, Softwaretechnik)

Anwendungen:I SoftwarepraktikumI weitere Sprachkonzepte in LV Prinzipien v.

ProgrammiersprachenI LV Programmverifikation (vorw. f. imperative Programme)

Page 12: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Gliederung der Vorlesung

I Terme, TermersetzungssystemeI algebraische Datentypen, Pattern Matching,I Rekursive Datenypen, RekursionsschemataI Funktionen (polymorph, höherer Ordnung), Lambda-KalkülI Typklassen zur Steuerung der PolymorphieI Bedarfsauswertung, unendl. Datenstrukturen

Page 13: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Organisation der Lehrveranstaltung

I jede Woche eine VorlesungI Hausaufgaben:

I schriftliche Übungen,I autotool

I jede Woche eine Übung / PraktikumI Beispiele,I Besprechung der schriftlichen Aufgaben,I autotool

Prüfungsvorleistung:regelmäßiges (d.h. innerhalb der jeweiligen Deadline) underfolgreiches (ingesamt ≥ 50% der Pflichtaufgaben) Bearbeitenvon Übungsaufgaben.

Prüfung: Klausur (ohne Hilfsmittel)

Page 14: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

LiteraturSkript voriges Semester:http://www.imn.htwk-leipzig.de/~waldmann/edu/ss14/fop/folien/mainFolien aktuelles Semester:http://www.imn.htwk-leipzig.de/~schwarz/lehre/ss15/dpBücher:

I Graham Hutton: Programming in Haskell, Cambridge 2007I Klassiker (englisch):http://haskell.org/haskellwiki/Books

I deutsch:I Peter Pepper und Petra Hofstedt:

Funktionale Programmierung. Sprachdesign undProgrammiertechnik Springer 2006

I Manuel Chakravarty und Gabriele Keller:Einführung in die Programmierung mit HaskellPearson 2004

online: http://www.haskell.org/Informationen, Download, Dokumentation, Tutorials, . . .

Page 15: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Werkzeug und StilDie Grenzen meiner Sprache bedeuten die Grenzen meinerWelt.

Ludwig Wittgenstein

speziell in der Informatik:We are all shaped by the tools we use, in particular: theformalisms we use shape our thinking habits, for better or forworse, and that means that we have to be very careful in thechoice of what we learn and teach, for unlearning is not reallypossible.(Many years ago, if I could use a new assistant, oneprerequisite would be No prior exposure to FORTRAN", and athigh schools in Siberia, the teaching of BASIC was notallowed.)

Edsger W. Dijkstra

aus E. W. Dijkstra Archivehttp://www.cs.utexas.edu/~EWD/

Page 16: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Konzepte und Sprachen

Funktionale Programmierung ist ein Konzept.

Realisierungen:I in prozeduralen Sprachen:

I Unterprogramme als Argumente (in Pascal)I Funktionszeiger (in C)

I in OO-Sprachen: BefehlsobjekteI Multi-Paradigmen-Sprachen:

I Lambda-Ausdrücke in C#, Scala, ClojureI funktionale Programmiersprachen (LISP, ML, Haskell)

Die Erkenntnisse sind sprachunabhängig.

I A good programmer can write LISP in any language.I Learn Haskell and become a better Java programmer.

Page 17: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Geschichte

ab ca. 1930 Alonzo Church λ-Kalkülab ca. 1950 John McCarthy LISPab ca. 1960 Peter Landin ISWIMab ca. 1970 John Backus FP

Robin Milner MLDavid Turner Miranda

ab 1987 Haskell

Page 18: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Warum Haskell?

I deklarativ, Nähe zum (mathematischen) ModellI keine Nebenwirkungen (klare Semantik)I Funktionen sind Daten (Funktionen höherer Ordnung)I starkes TypsystemI TypklassenI lazy evaluation (ermöglicht Rechnen mit unendlichen

Datenstrukturen)I kompakte Darstellung (kurze Programme)I Modulsystem

Page 19: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Entwicklung von Haskell-Programmen

Haskell-Interpreter: ghci, Hugs

Haskell-Compiler: ghc

Entwicklungsumgebungen:I http://leksah.org/

I http://eclipsefp.sourceforge.net/

I http://www.haskell.org/visualhaskell/

alles kostenlos und open source

Real Programmers (http://xkcd.com/378/)

Page 20: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Wiederholung: Terme

Signatur (funktional)Σ (ΣF ) ist Menge von Funktionssymbolen mitStelligkeiten

Term t = f (t1, . . . , tk ) in Signatur Σ istI Funktionssymbol der Stelligkeit k :

(f , k) ∈ Σ der Stelligkeit kmit Argumenten t1, . . . , tk , die selbst Termesind.

Term(Σ,X) = Menge aller Terme über Signatur Σ mitIndividuenvariablen aus X

Graphentheorie: ein Term ist eingerichteter, geordneter, markierter Baum

Datenstrukturen:I Funktionssymbol = Konstruktor,I Term = Baum

Page 21: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Beispiele: Signatur, Terme

I Signatur: Σ1 = {Z/0,S/1, f/2}Elemente aus Term(Σ1):Z (), S(S(Z ())), f (S(S(Z ())),Z ())

I Signatur: Σ2 = {E/0,A/1,B/1}Elemente aus Term(Σ2): . . .

Page 22: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Haskell-Programme

Programm: Menge von Funktions-DefinitionenGleichungen zwischen Termen

Ausdruck: TermAusführung: Auswertung des Ausdruckes (Bestimmung seines

Wertes)Pattern matching, Reduktion, (Termersetzung)

Semantik:Funktion von Eingabe (Ausdruck) auf Ausgabe (Wert)

I keine Variablen, also keine Programmzustände(kein Aufruf-Kontext)

I Wert jeder Funktion(sanwendung) hängt ausschließlichvon den Werten der Argumente ab

Page 23: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Syntax

Ausdrücke : Termez.B. 2 + x * 7 oder double 2

Funktionsdefinition : Gleichung zwischen zwei Ausdrückenz.B. inc x = x + 1

Programm :I Folge (Liste) von FunktionsdefinitionenI Ausdruck

Page 24: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Ausdrücke

Ausdruck = Term (Baumstruktur)

Jeder Ausdruck hatI einen Typ undI einen Wert

Berechnung des Wertes durch schrittweise Reduktion(Termersetzung)

Page 25: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Beispiele

Ausdruck 7 hatI den Typ Int

I den Wert 7

Ausdruck 3 * 7 + 2 hatI den Typ Int

I den Wert . . .

Reduktion : (rekursive) Berechnung des Wertes

Page 26: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Funktionsdeklarationen

double :: Int -> Int (Typdeklaration)double x = x + x (Funktionsdefinition)

Ausdruck double 3 hatI den Typ Int

I den Wert 6

Ausdruck double (double 3) hatI den Typ Int

I den Wert . . .

Ausdruck double hatI den Typ Int -> Int

I den Wert x 7→ x + x (mathematische Notation)λx .(x + x) (λ-Kalkül)

Page 27: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Was bisher geschah

I deklarative ProgrammierungI funktional:

Programm: Menge von Termgleichungen, TermAuswertung: Pattern matching, Termumformungen

I logisch:Programm: Menge von Regeln (Horn-Formeln), FormelAuswertung: Unifikation, Resolution

I funktionale Programmierung in Haskell:I nebenwirkungsfreiI lazy evaluation (ermöglicht unendliche Datentypen)I kompakte Darstellung

I Praktikum: Termersetzung, ghci, Prelude

Page 28: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Bezeichnungen für Teilterme

Position : Folge von natürlichen Zahlen(bezeichnet einen Pfad von der Wurzel zu einemKnoten)Beispiel: für Signatur Σ = {(g,2), (f ,1), (c,0)}und Term t = f (g(f (f (c)), c)) ∈ TermΣ, ∅ist [0,1] eine Position in t ,aber [1], [0,1,0], [0,0,1] nicht

Pos(t) Menge aller Positionen des Terms t ∈ Term(Σ,X)(rekursive) Definition: für t = f (t1, . . . , tk )gilt Pos(t) ={[]} ∪ {[i − 1] ++{p | i ∈ {1, . . . , k} ∧ p ∈ Pos(ti)}.

dabei bezeichnen:I [] die leere Folge,

I [i] die Folge der Länge 1 mit Element i ,

I ++ den Verkettungsoperator für Folgen

Page 29: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Operationen mit (Teil)Termen

t [p] : Teilterm von t an Position pBeispiele:

I f (g(f (f (c)), c))[0,0] = f (f (c))I f (g(f (f (c)), c))[0,1] = . . .

(induktive) Definition (über die Länge von p):IA p = [] : t [] = tIS p = i ++p′: f (t1, . . . , tn)[p] = ti [p′]

t [p := s] : wie t , aber mit Term s statt t [p] an Position pBeispiele:

I f (g(f (f (c)), c))[[0,0] := c] = f (g(c, c))I f (g(f (f (c)), c))[[0,1] := f (c)] = . . .

(induktive) Definition (über die Länge von p): . . .

Page 30: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Operationen mit Variablen in Termen

I Menge Term(Σ,X) aller Terme über Signatur Σ mitVariablen aus XBeispiel: Σ = {Z/0,S/1, f/2},X = {y},f (Z (), y) ∈ Term(Σ,X).

I Substitution σ: partielle Abbildung X→ Term(Σ,X)Beispiel: σ1 = {(y ,S(Z ()))}

I eine Substitution auf einen Term anwenden: tσ:Intuition: wie t , aber statt v ∈ X immer σ(v)Beispiel: f (Z (), y)σ1 = f (Z (),S(Z ()))Definition durch Induktion über t

Page 31: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Termersetzungssysteme

Daten : Terme (ohne Variablen)Regel : Paar (l , r) von Termen mit Variablen

Programm R: Menge von RegelnBsp: R = {(f (Z (), y), y), (f (S(x), y),S(f (x , y)))}

Relation→R : Menge aller Paare (t , t ′) mitI es existiert (l , r) ∈ RI es existiert Position p in tI es existiert Substitutionσ : (var(l) ∪ var(r))→ Term(Σ)

I so dass t [p] = lσ und t ′ = t [p := rσ].

Page 32: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Termersetzungssysteme als Programme

I →R beschreibt einen Schritt der Rechnung von R,I transitive Hülle→∗R beschreibt Folge von Schritten.I Resultat einer Rechnung ist Term in R-Normalform

(ohne→R-Nachfolger)

Dieses Berechnungsmodell ist im allgemeinennichtdeterministisch R1 = {C(x , y)→ x ,C(x , y)→ y}

(ein Term kann mehrere→R-Nachfolger haben,ein Term kann mehrere Normalformen erreichen)

nicht terminierend R2 = {p(x , y)→ p(y , x)}(es gibt eine unendliche Folge von→R-Schritten,es kann Terme ohne Normalform geben)

Page 33: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Konstruktor-SystemeFür TRS R über Signatur Σ:Symbol s ∈ Σ heißt

definiert , wenn ∃(l , r) ∈ R : l[] = s(. . .)

Konstruktor , sonst

Das TRS R heißt Konstruktor-TRS, fallsdie definierten Symbole links nur in den Wurzeln vorkommen(rechts egal)

Übung: diese Eigenschaft formal spezifizieren

Beispiele:I R1 = {a(b(x))→ b(a(x))} über Σ1 = {a/1,b/1},I R2 = {f (f (x , y), z)→ f (x , f (y , z))} über Σ2 = {f/2}:

definierte Symbole? Konstruktoren? Konstruktor-System?

Funktionale Programme sind ähnlich zu Konstruktor-TRS.

Page 34: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Selbsttest-Übungsaufgaben

zur Klausur-Vorbereitung (statt Praktikum diese Woche) zu

I SignaturenI TermenI SubstitutionenI TermersetzungsysstemenI Normalformen

unterhttp://www.imn.htwk-leipzig.de/~waldmann/edu/ss14/fop/folien/main/node28.html

Page 35: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Funktionale Programme. . . sind spezielle Term-Ersetzungssysteme.

Beispiel:Signatur: S einstellig, Z nullstellig, f zweistellig.Ersetzungssystem {f (Z , y)→ y , f (S(x), y)→ S(f (x , y))}.Startterm f (S(S(Z )),S(Z )).

entsprechendes funktionales Programm:

data N = Z | S N

f :: N -> N -> Nf x y = case x of

{ Z -> y ; S x’ -> S (f x’ y) }

Aufruf: f (S (S Z)) (S Z)

Auswertung = Folge von Ersetzungsschritten→∗RResultat = Normalform (hat keine→R-Nachfolger)

Page 36: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

data und case

typisches Vorgehen beim Programmieren einer Funktion

f :: T -> ...

Für jeden Konstruktor des Datentyps

data T = C1 ...| C2 ...

schreibe einen Zweig in der Fallunterscheidung

f x = case x ofC1 ... -> ...C2 ... -> ...

Page 37: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Peano-Zahlen

data N = Z | S Nderiving Show

plus :: N -> N -> Nplus x y = case x of

Z -> yS x’ -> S (plus x’ y)

Beispiel (Tafel): Multiplikation

Page 38: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Was bisher geschah

I Wiederholung Signatur, TermI Termersetzungssysteme (TRS)I Konstruktoren, definierte SymboleI Konstruktor-SystemeI funktionale Programmierung

Programm: Menge von Termgleichungen (TRS)Ausdruck (dessen Wert zu bestimmen ist): Term

Auswertung: Pattern matching, TermumformungenI Haskell:

I nebenwirkungsfreiI kompakte Darstellung

I Praktikum: ghci, Prelude, Typen, Hoogle

Page 39: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Vordefinierte Haskell-Datentypen

einfache Datentypen, z.B.Int ganze Zahlen (feste Länge)Integer ganze Zahlen (beliebige Länge)Bool Wahrheitswerte (False, True)Char ASCII-SymboleFloat, Double

zusammengesetzt (Typkonstruktoren):I Tupel (a, b), (a, b, c), (a1, a2, ...)

z.B. (1, True, ’B’) :: (Int, Bool, Char)

I Listen (polymorph) [a],z.B. [3,5,2] :: [Int],[[’I’, ’N’],[’B’]] :: [[Char]]

I String = [Char], z.B. "INB" = [’I’,’N’,’B’]

Page 40: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Definition von Funktionen

Programmstrukturen:I Verzweigung (Fallunterscheidung)I Rekursion

Beispiel:

sumto :: Int -> Int

sumto n = if n < 0then 0else n + sumto (n-1)

Page 41: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Funktionsdeklarationen (Wiederholung)add :: Int -> Int -> Int (Typdeklaration)add x y = x + y (Funktionsdefinition)Ausdruck add 3 5 hat

I den Typ IntI den Wert 8

Ausdruck add (add 3 5) 1 hatI den Typ IntI den Wert . . .

Ausdruck add hatI den Typ Int -> Int -> IntI den Wert (x , y) 7→ x + y (mathematische Notation)λx .λy .(x + y) (λ-Kalkül)

Ausdruck add 3 hatI den Typ Int -> IntI den Wert y 7→ 3 + y (mathematische Notation)λy .(3 + y) (λ-Kalkül)

(partielle Anwendung von add)

Page 42: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Typinferenz

Typinferenzregel:f :: A→ B e :: A

f e :: B

Man bemerke die Analogie zur logischen Inferenzregel

Modus Ponens:A→ B A

B

Beispiel: Typ von add 3, add 3 5

Page 43: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Beispiele Typinferenz

True :: BoolFalse :: Bool

neg :: Bool -> Boolneg True = Falseneg False = True

Typ von neg True, neg (neg True)

len :: [a] -> Intgerade :: Int -> Bool

Typ von[1,2,3], len [1,2,3], gerade ( len [1,2,3] )

Page 44: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

CurryingIdee:Jede Funktion mit mehreren Argumenten lässt sich alsgeschachtelte Funktionen mit je einem Argument auffassen(und aufschreiben)Beispiel:Die folgenden Zeilen definieren dieselbe Funktion vom Typg :: Int -> Int -> Bool

I g m n = m < n

I g m = \ n -> m < n (g m) = λn.(m < n)

I g = \ m n -> m < n g = λm.λn.(m < n)

mit Argument-Tupel (Achtung anderer Typ):g’ :: (Int, Int) -> Boolg’ (m, n) = m < nin mathematischer Notation:zweistellig: C(A×B) ist isomorph zu (CB)A

(n − 1)-stellig: A(A1×···×An−1)n ist isomorph zu

(· · ·(

AAn−1n

)· · ·)A1

Page 45: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Konstruktion zusammengesetzter Datentypen

Operationen:I (kartesisches) ProduktI Vereinigung (Fallunterscheidung)

z.B. AufzählungstypenI Rekursion, z.B. Listen, Bäume, Peano-ZahlenI Potenz, Funktionen

Page 46: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Algebraische Datentypen

data Foo = Foo { bar :: Int, baz :: String }deriving Show

Bezeichnungen (benannte Notation):I data Foo ist TypnameI Foo { .. } ist KonstruktorI bar, baz sind Komponenten

x :: Foox = Foo { bar = 3, baz = "hal" }

Bezeichnungen (positionelle Notation)

data Foo = Foo Int Stringy = Foo 3 "bar"

Mathematisch: ProduktFoo = Int × String

Page 47: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Datentyp mit mehreren Konstruktoren

Beispiel (selbst definiert):

data T = A { foo :: Int }| B { bar :: String }

deriving Show

Beispiel (in Prelude vordefiniert)

data Bool = False | True

data Ordering = LT | EQ | GT

Mathematisch: (disjunkte) VereinigungBool = { False } ∪ { True }

Page 48: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Fallunterscheidung, Pattern Matching

data T = A { foo :: Int }| B { bar :: String }

Fallunterscheidung:

f :: T -> Intf x = case x of

A {} -> foo xB {} -> length $ bar x

Pattern Matching (Bezeichner n,l werden lokal gebunden):

f :: T -> Intf x = case x of

A { foo = n } -> nB { bar = l } -> length l

Page 49: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Rekursive DatentypenWiederholung Peano-Zahlen:

data Nat = Z| S Nat

Menge aller Peano-Zahlen: Nat = {Z} ∪ {Sn | n ∈ Nat}Addition:

add :: Nat -> Nat -> Natadd Z y = yadd ( S x ) y = S ( add x y )

oder

add :: Nat -> Nat -> Natadd x y = case x of

Z -> yS x’ -> S ( add x’ y )

Definition weiterer Operationen: Multiplikation, Potenz

Page 50: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Wiederholung ADT Nat

Sorten: N (natürliche Zahlen)Signatur: Z :: N

S :: N -> Nadd :: N -> N -> Nmult :: N -> N -> N...

Axiome: ∀x ∀y ∀u:add Z x = x = add x Zadd x y = add y xadd x ( add y u ) = add ( add x y ) umult Z x = Z = mult x Zmult ( S Z ) x = x = mult x ( S Z )mult x y = mult y xmult x ( mult y u ) = mult ( mult x y ) u. . .

Nachweis durch strukturelle Induktion (Tafel)

Page 51: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Wiederholung Strukturelle InduktionInduktive Definition strukturierter Daten (rekursive Datentypen):

IA: BasisfälleIS: rekursive Fälle, Vorschrift zur Konstruktion

zusammengesetzter Daten

Induktive Definition von Funktionen über strukturierten Daten:

IA: Definition des Funktionswertes für BasisfälleIS: Berechnung des Funktionswertes der

zusammengesetzten Daten aus den Funktionswertender Teile

Prinzip der strukturellen Induktionzum Nachweis einer Aussage A über strukturierte Daten:

IA: Nachweis, dass A für alle Basisfälle giltIS: I Hypothese (Voraussetzung): A gilt für Teildaten

I Behauptung: A gilt für aus Teildatenzusammengesetzte Daten

I Induktionsbeweis: Nachweis, dass Behauptungaus Hypothese folgt.

Page 52: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Was bisher geschah

I Deklarative vs. imperative ProgrammierungI Funktionale Programmierung:

Programm: Menge von Gleichungen von Termen(Konstruktor-System)

Ausdruck hat Typ und Wert (zu berechnen)Ausführung: Pattern matching, Termersetzung

Haskell:I Algebraische Datentypen

und Pattern MatchingI Rekursive Datentypen (Peano-Zahlen)I Rekursive FunktionenI strukturelle Induktion

Page 53: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Wiederholung Haskell-Typen

I vordefinierte Typen,z. B. Bool, Char, Int, Float, String, ...

I Typvariablen, z.B. a, b ,...I Konstruktion zusammengestzter Typen:

I selbstdefiniert constr typ1 ... typnI Listen-Konstruktor [ typ ]I Tupel-Konstruktor ( typ1, ..., typn )I Funktions-Konstruktor typ1 -> typ2

Page 54: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Algebraische Datentypen – WiederholungOperationen:

I Produkt A× BBeispiel:

data Punkt = Punkt { x :: Float, y :: Float}data Kreis = Kreis { mp :: Punkt, radius :: Float }

I (disjunkte) Vereinigung A ∪ BBeispiel Wahrheitswerte (vordefiniert)

data Bool = True | False

data Shape = Circle { mp :: Punkt, radius :: Float }| Rect { ol, ur :: Punkt}

umfang :: Shape -> Floatumfang s = case s of

Circle {} -> 2 * pi * ( radius s )Rect ol ur -> ...

I Potenz AB = {f : B → A}z.B. gerade_laenge :: String -> Bool

Page 55: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Algebraische Datentypen – Beispiel

data HR = N | O | S | Wdata Turn = Links | Rechts | Um

dreh :: Turn -> HR -> HRdreh Rechts x = case x of

N -> OO -> SS -> WW -> N

dreh Links x = ...

drehs :: [ Move ] -> HR -> HRdrehs ( m : ms ) x = dreh m ( drehs ms x )

Page 56: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Algebraische Datentypen – Beispieledata Pair a b = Pair a b (Produkt)

data Either a b = Left a | Right b (Vereinigung)

data Maybe a = Nothing | Just a (Vereinigung)

Binärbäume (rekursiv):

data Bin a = Leaf| Branch (Bin a) a (Bin a)

Spezialfall Listen (Unärbäume):

data List a = Nil | Cons a (List a)

Bäume (mit beliebigen Knotengraden):

data Tree a = Node a (List (Tree a))

Page 57: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Typsynonyme(Um-)Benennung vorhandener Typen (meist als Kurzform)

Beispiel:

type String = [ Char ]type Name = Stringtype Telefonnummer = Inttype Telefonbuch = [ ( Name , Telefonnummer ) ]

nummern :: Name -> Telefonbuch -> [ Telefonnummer ]nummern name [] = []nummern name ( ( n , t ) : rest ) ...

allgemeiner: Wörterbücher

type Woerterbuch a b = [ ( a, b ) ]

rekursive Typen sind nicht als Typsynonym definierbar

Page 58: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Typsynonyme – BeispielZwei-Personen-Brettspiel (auf rechteckigem Spielfeld)

I Spieler ziehen abwechselndI Jeder Spieler hat Spielsteine seiner Farbe auf mehreren

Positionen des Spielfeldes

Spielfeld:

type Feld = ( Int, Int )type Belegt = [ Feld ]type Spieler = Bool

Spielzustand:

type Zustand = ( Belegt, Belegt, Spieler )

Spiel:

type Spiel = [ Zustand ]

Page 59: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Polymorphienicht polymorphe Typen:tatsächlicher Argumenttyp muss mit dem deklariertenArgumenttyp übereinstimmen:

f :: A→ B e :: A(f e) :: B

polymorphe Typen:Typ von f :: A -> B und Typ von e :: A’ könnenTypvariablen enthalten.A und A’ müssen unfizierbar (eine gemeinsame Instanzbesitzen) aber nicht notwendig gleich sein.σ = mgu(A,A′) allgemeinster UnifikatorTyp von f wird dadurch spezialisiert auf σ(A)→ σ(B)

Typ von e wird dadurch spezialisiert auf σ(A′)allgemeinster Typ von ( f e ) ist dann σ(B)

Page 60: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Wiederholung SubstitutionenSubstitution: partielle Funktion θ : X → Term(Σ,X )

Notation als Aufzählung [x 7→ t1, y 7→ t2, . . .]Anwendung einer Substitution:

I s[x 7→ t ] ist der Term, welcher aus dem Term s durch Ersetzungjedes Vorkommens der Variable x durch t entsteht

I ϕ[x 7→ t ] ist die Formel, die aus der Formel ϕ durch Ersetzungjedes freien Vorkommens der Variable x durch t entsteht

Beispiele:

I g(x , f (a))[x 7→ b] = g(b, f (a))

I h(y , x , f (g(y ,a)))[x 7→ g(a, z), y 7→ a] = h(a,g(a, z), f (g(a,a)))

I g(x , f (a))[x 7→ b, y 7→ a] = g(b, f (a))

I g(b, f (y))[x 7→ b, y 7→ a] = g(b, f (a))

I für θ = [x 7→ b], σ = [y 7→ f (a)] (auch θ(x) = b, σ(y) = f (a) ) gilt(h((b, f (y)), k(x)))θσ = σ(θ(h((b, f (y)), k(x)))= σ(h((b, f (y)), k(b)) = h((b, f (f (a))), k(b))

Page 61: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

UnifikatorSubstitution θ heißt genau dann Unifikator der Termet1 und t2 (θ unifiziert t1 und t2), wenn θ(t1) = θ(t2) gilt.Beispiele:

1. θ = [x 7→ b, y 7→ a] unifiziert t1 = g(x , f (a)) und t2 = g(b, f (y))

2. [x 7→ g(g(y)), z 7→ g(y)] unifiziert f (x ,g(y)) und f (g(z), z) (undf (g(z),g(y)).

3. [x 7→ g(g(a)), y 7→ a, z 7→ g(a)]unifiziert f (x ,g(y)) und f (g(z), z).

4. [x 7→ g(g(y)), z 7→ g(y), v 7→ f (a)]unifiziert f (x ,g(y)) und f (g(z), z).

Terme t1, t2 heißen genau dann unifizierbar,wenn ein Unifikator für t1 und t2 existiert.Beispiele:

1. g(x , f (a)) und g(b, f (y)) sind unifizierbar,f (g(a, x)) und f (g(f (x),a)) nicht.

2. h(a, f (x),g(a, y)) und h(x , f (y), z) sind unifizierbar,h(f (a), x) und h(x ,a) nicht.

Page 62: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Was bisher geschah

I Deklarative vs. imperative ProgrammierungI Funktionale Programmierung:

Programm: Menge von Gleichungen von Termen(Konstruktor-System)

Ausdruck hat Typ und Wert (zu berechnen)Ausführung: Pattern matching, Termersetzung

Haskell:I Algebraische Datentypen

und Pattern MatchingI Rekursive Datentypen (Peano-Zahlen)I Rekursive FunktionenI strukturelle Induktion

Page 63: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Typ-Inferenz in Haskell

Inferenzregel:f :: A→ B e :: A

(f e) :: B

für polymorphe Typen:

f :: A→ B e :: A′

(f e) ::?

Unifikator σ der Typausdrücke (Terme) A und A′

(Substitution mit σ(A) = σ(A′))

f :: σ(A)→ σ(B) e :: σ(A′)(f e) :: σ(B)

Page 64: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Wiederholung UnifikatorSubstitution θ heißt genau dann Unifikator der Termet1 und t2 (θ unifiziert t1 und t2), wenn θ(t1) = θ(t2) gilt.Beispiele:

1. θ = [x 7→ b, y 7→ a] unifiziert t1 = g(x , f (a)) und t2 = g(b, f (y))

2. [x 7→ g(g(y)), z 7→ g(y)] unifiziert f (x ,g(y)) und f (g(z), z) (undf (g(z),g(y)).

3. [x 7→ g(g(a)), y 7→ a, z 7→ g(a)]unifiziert f (x ,g(y)) und f (g(z), z).

4. [x 7→ g(g(y)), z 7→ g(y), v 7→ f (a)]unifiziert f (x ,g(y)) und f (g(z), z).

Terme t1, t2 heißen genau dann unifizierbar,wenn ein Unifikator für t1 und t2 existiert.Beispiele:

1. g(x , f (a)) und g(b, f (y)) sind unifizierbar,f (g(a, x)) und f (g(f (x),a)) nicht.

2. h(a, f (x),g(a, y)) und h(x , f (y), z) sind unifizierbar,h(f (a), x) und h(x ,a) nicht.

Page 65: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

(Keine) Ordnung auf Unifikatoren

Für zwei Unifikatoren σ, θ der Terme s, t gilt:

Relation R auf Substitutionen:

(σ, θ) ∈ R gdw. ∃ρ : σ ◦ ρ = θ

(Man bemerke die Analogie zur Teilerrelation)

Beispiele:I ([x 7→ y ], [x 7→ a, y 7→ a]) ∈ RI ([x 7→ y ], [y 7→ x ]) ∈ RI ([y 7→ x ], [x 7→ y ]) ∈ R

Diese Relation R ist reflexiv und transitiv, aber nichtantisymmetrisch.

Page 66: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Ordung auf Unifikatoren

σ heißt genau dann allgemeiner als θ, wenn eine Substitution ρ(die nicht nur Umbenennung ist) existiert, so dass σ ◦ ρ = θ

Diese Relation ist eine Halbordnung

Beispiele: Unifikatoren für f (x ,g(y)), f (g(z), z)

1. Unifikator [x 7→ g(g(y)), z 7→ g(y)] ist allgemeiner als[x 7→ g(g(a)), z 7→ g(a)]ρ = [y 7→ a]

2. Unifikator [x 7→ g(g(y)), z 7→ g(y)] ist allgemeiner als[x 7→ g(g(y)), z 7→ g(y), v 7→ g(b)]ρ = [v 7→ g(b)]

Page 67: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Allgemeinster Unifikator

Zu unifizierbaren Termen s, t existiert (bis auf Umbenennungder Variablen) genau ein Unifikator θ mit der folgendenEigenschaft:Für jeden Unifikator σ für s, t ist θ allgemeiner als σ.Dieser heißt allgemeinster Unifikator θ = mgu(s, t) von s und t .

(analog ggT)

Beispiele:I mgu(f (x ,a), f (g(b), y)) = [x 7→ g(b), y 7→ a]

I mgu(f (x ,g(y)), f (g(z), z)) = [x 7→ g(g(y)), z 7→ g(y)]

Page 68: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Unifizierbarkeit

I Jeder Term t ist mit t unifizierbar.allgemeinster Unifikator mgu(t , t) = []

I Jeder Term t ist mit jeder Variable x ∈ X, die nicht in tvorkommt, unifizierbar.allgemeinster Unifikator mgu(t , t) = [x 7→ t ]

I f (t1, . . . , tn) und g(s1, . . . , sm) sind nicht unifizierbar,falls f 6= g oder n 6= m

I θ ist Unifikator für f (t1, . . . , tn), f (s1, . . . , sn) gdw.∀i ∈ {1, . . . ,n} : θ unifiziert ti und si

Page 69: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Unifikation – Aufgabe

Eingabe: Terme s, t ∈ Term(Σ,X)

Ausgabe: ein allgemeinster Unifikator (mgu)σ : X→ Term(Σ,X) mit sσ = tσ.

Satz: Jedes Unifikationsproblem istI entweder gar nichtI oder bis auf Umbenennung eindeutig

lösbar.

Page 70: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Unifikation – Algorithmus

Berechnung von σ = mgu(s, t) für Terme s, t ∈ Term(Σ,X)durch Fallunterscheidung:

I s ∈ X:falls s 6∈ var(t), dann σ = [s 7→ t ],sonst nicht unifizierbar

I t ∈ X: symmetrischI s = f (s1, . . . , sm) und t = g(t1, . . . , tn):

falls f 6= g oder m 6= n, dann nicht unifizierbarsonst σ = mgu(s1, t1) ◦ · · · ◦mgu(sm, tm)

Dabei gilt für jede Substitution θ:

θ◦„nicht unifizierbar“ = „nicht unifizierbar“◦θ = „nicht unifizierbar“

Page 71: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Unifikationsalgorithmus – Beispiele

I mgu(f (x ,h(y), y), f (g(z), z,a)) =[x 7→ g(h(a)), z 7→ h(a), y 7→ a]

I mgu (k(f (x),g(y ,h(a, z))), k(f (g(a,b)),g(g(u, v),w))) =[x 7→ g(a,b), y 7→ g(u, v),w 7→ h(a, z)]

I mgu(k(f (a),g(x)), k(y , y)) existiert nichtI mgu(f (x ,g(a, z)), f (f (y), f (x)) existiert nichtI mgu(f (x , x), f (y ,g(y)) existiert nichtI mgu(f (x ,g(y)), f (y , x) existiert nicht

Page 72: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Unifikation von Haskell-Typen – Beispiele

I last :: [a] -> aTyp von [ 3, 5 .. 10 ] ist [Int]angewendete Instanz der Funktionlast :: [Int] -> Int ,

der Typ von last [ 3, 5 .. 10 ] ist also Int

I take :: Int -> [a] -> [a]Typ von take 1 ?Typ von take 1 [ "foo", "bar" ] ?

Page 73: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Was bisher geschahI Deklarative vs. imperative ProgrammierungI Funktionale Programmierung:

Programm: Menge von Gleichungen von Termen(Konstruktor-System)

Ausdruck hat Typ und Wert (zu berechnen)Ausführung: Pattern matching, Termersetzung

Funktionale Programmierung in HaskellI rekursive FunktionenI algebraische Datentypen und Pattern MatchingI rekursive Datentypen

(Peano-Zahlen)I strukturelle InduktionI Typen, Typ-Konstruktoren, Typ-SynonymeI PolymorphieI Typ-Inferenz, Unifikation

Page 74: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Datentyp Liste (polymorph)data List a = Nil

| Cons { head :: a, tail :: List a}

oder kürzer (vordefiniert)

data [a] = []| a : [a]

Pattern Matching:

f :: [a] -> ...f xs = case xs of

[] -> ...(x : xss) -> ...

Beispiel:

append :: [a] -> [a] -> [a]append xs ys = case xs of

[] -> ys(x : xss) -> x : (append xss ys)

Page 75: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Strukturelle Induktion über Listen

zum Nachweis von Eigenschaften wie z.B.I append xs [] = xs

I append ist assoziativ, d.h

append xs (append ys zs) = append (append xs ys) zs

Länge der Eingabeliste

len :: [a] -> Intlen xs = case xs of

[] -> 0(x : xss) -> 1 + len xss

Strukturelle Induktion zum Nachweis vonlen ( append xs ys ) = len xs + len ys

Page 76: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Mehr Beispiele

Summe aller Elemente der Eingabeliste

sum :: [Int] -> Intsum xs = case xs of

[] -> ...(x : xss) -> ...

jedes Element der Eingabeliste verdoppeln

doubles :: [Int] -> [Int]doubles xs = case xs of

[] -> []( y : ys ) -> ... : (doubles ys)

Strukturelle Induktion zum Nachweis vonsum ( doubles xs ) = 2 * ( sum xs )

Page 77: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Sortierte Listen(aufsteigend geordnet)

sortiert :: [Int] -> Boolsortiert xs = case xs of

[] -> True[ _ ] -> True(x : y : ys) -> x <= y && sortiert (y : ys)

sortiertes Einfügen:

insert :: Int -> [Int] -> [Int]insert y xs = case xs of

[] -> ...( x : xs ) -> if ...

then ...else ...

Strukturelle Induktion zum Nachweis von:Aus sortiert xs folgt sortiert ( insert x xs )

Page 78: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

List Comprehensions – MotivationMenge der Quadrate aller geraden Zahlen zwischen 0 und 20:

{i2 | i ∈ {0, . . . ,20} ∧ i ≡ 0 (mod 2)}

Liste der Quadrate aller geraden Zahlen zwischen 0 und 20:(i2)

i∈[0,...,20],i≡0 (mod 2)

Definition der Menge / Liste enthält:Generator i ∈ [0, . . . ,20]

Funktion 2 : N→ NBedingung i ≡ 0 (mod 2)

als List Comprehension in Haskell:

[ i ^ 2 | i <- [0 .. 20], rem i 2 == 0]

Page 79: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

List ComprehensionsI mit einem Generator[ f x | x <- ..]

z.B. [ 3 * x | x <- [1 .. 5] ]I mit mehreren Generatoren[ f x1 .. xn |x1 <- .., .. , xn <- .. ]

z.B.[ ( x , y ) | x <- [1 .. 3], y <- [0,1] ]

[ (x, x * y, x + z) | x <- [1 .. 5], y <- [0 .. 2], z <- [3 ..] ]

I mit Bedingungen:[ f x1 .. xn | x1 <- .., .. , xn <- ..

, r1 xi xj , .. , rk xi xj ]

z.B.[ ( x , y ) | x <- [1 .. 5], y <- [ 0 .. 4 ]

, x + y > 5, rem x 2 == 0]

Page 80: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Beispiele

[ ( x, y ) | x <- [ 1 .. 3 ], y <- [ 4 , 5 ] ]

[ ( x, y ) | y <- [ 1 .. 3 ], x <- [ 4 , 5 ] ]

[ x * y | x <- [ 1 .. 3 ], y <- [ 2 .. 4 ] ]

[ x * y | x <- [1 .. 3], y <- [2 .. 4], x < y ]

[ ’a’ | _ <- [1 .. 4] ]

[ [1 .. n] | n <- [0 .. 5] ]

hat welchen Typ?

[ x | xs <- xss , x <- xs ] ]

xss hat welchen (allgemeinsten) Typ?

Page 81: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Mehr Beispiele

teiler :: Int -> [ Int ]

teiler x = [ y | y <- [ 1 .. x ], rem x y == 0 ]

prim :: Int -> Bool

prim x = ( teiler x ) == [ 1, x ]

primzahlen :: [ Int ]

primzahlen = [ x | x <- [ 2 .. ], prim x ]

( später auch anders )

Page 82: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Was bisher geschah

I Deklarative vs. imperative ProgrammierungI Funktionale Programmierung:

Programm: Menge von Gleichungen von Termen(Konstruktor-System)

Ausdruck hat Typ und Wert (zu berechnen)Ausführung: Pattern matching, Termersetzung

Funktionale Programmierung in HaskellI rekursive FunktionenI algebraische Datentypen und Pattern MatchingI rekursive Datentypen

I Peano-Zahlen,I Listen

I strukturelle InduktionI Typen, Polymorphie, Typ-Inferenz

Page 83: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Datentyp Binärbaum (polymorph)data Bintree a = Leaf {}

| Branch { left :: Bintree a,key :: a,right :: Bintree a }

Beispiel:

t :: Bintree Intt = Branch {

left = Branch { left = Leaf {},key = 5,right = Leaf {} },

key = 3,right = Branch {

left = Leaf {},key = 2,right = Branch { left = Leaf {},

key = 4,right = Leaf {} }}}

Page 84: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Pattern Matching

data Bintree a = Leaf {}| Branch { left :: Bintree a,

key :: a,right :: Bintree a }

f :: Bintree a -> ..f t = case t of

Leaf {} -> ..Branch {} -> ..

oder tiefer:

f :: Bintree a -> ..f t = case t of

Leaf {} -> ..Branch { left = l, key = k, right = r } -> ..

Page 85: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Rekursion über binäre Bäume – BeispieleAnzahl der inneren Knoten

count :: Bintree a -> Intcount t = case t of

Leaf {} -> 0Branch {} -> count (left t)

+ 1 + count (right t)

Anzahl der Blätter:

leaves :: Bintree a -> Intleaves t = case t of

Leaf {} -> ...Branch {} -> ...

Summe der Schlüssel (Int):

bt_sum :: Bintree Int -> Intbt_sum t = case t of

Leaf {} -> ...Branch {} -> ...

Page 86: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Mehr Beispielejeden Schlüssel verdoppeln

doubles :: Bintree Int -> Bintree Intdoubles t = case t of

Leaf {} -> Leaf {}Branch {} -> ...

inorder :: Bintree a -> [a]inorder t = case t of

Leaf {} -> []Branch {} -> ...

vollständiger binärer Baum der Höhe h:

full :: Int -> Bintree Intfull h = if h > 0

then Branch { left = full (h-1),key = h,right = full (h-1) }

else Leaf {}

Page 87: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Strukturelle Induktion über Binärbäume

z.z. Jeder Binärbaum t mit Schlüsseln vom Typ ahat die Eigenschaft P

IA (t = Leaf): z.z.: Leaf hat die Eigenschaft PIS IV: Binärbäume l und r erfüllen P

IB: ∀ k :: a hat der BinärbaumBranch { left = l,

key = k,right = r }

die Eigenschaft P

zum Nachweis von Eigenschaften wie z.B.

I ∀ ( t :: Bintree Int ) :bt_sum (doubles t) = 2 * bt_sum t

I ∀ ( t :: Bintree Int ) :bt_sum t = list_sum ( inorder t )

Page 88: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Was bisher geschahI Deklarative vs. imperative ProgrammierungI Funktionale Programmierung:

Programm: Menge von Gleichungen von Termen(Konstruktor-System)

Ausdruck hat Typ und Wert (zu berechnen)Ausführung: Pattern matching, Termersetzung

Funktionale Programmierung in HaskellI rekursive FunktionenI algebraische Datentypen und Pattern MatchingI rekursive Datentypen

I Peano-Zahlen,I Listen,I Binärbäume

I strukturelle InduktionI Typen, Polymorphie, Typ-Inferenz

Page 89: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Wiederholung Datentyp Binärbaum (polymorph)data Bintree a = Leaf {}

| Branch { left :: Bintree a,key :: a,right :: Bintree a }

Beispiel:

t :: Bintree Intt = Branch {

left = Branch { left = Leaf {},key = 1,right = Leaf {} },

key = 3,right = Branch {

left = Leaf {},key = 4,right = Branch { left = Leaf {},

key = 6,right = Leaf {} }}}

Page 90: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Binäre SuchbäumeSuchbaum-Eigenschaft:Ein binärer Baum t :: Bintree Int ist genau dann einSuchbaum, wenn seine Knoten in Inorder-Durchquerung(aufsteigend) geordnet sind.

search_tree t = sortiert (inorder t)

mit

sortiert :: [ Int ] -> Boolsortiert [] = Truesortiert [ x ] = Truesortiert ( x : y : xs ) = ...

Einfügen eines Schlüssels in einen binären Suchbaum:

insert :: Int -> Bintree Int -> Bintree Intinsert x t = case t of

Leaf {} -> Branch { left = Leaf {},key = x,right = Leaf {} }

Branch {} -> ...

Page 91: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Sortieren durch Einfügen in binäre Suchbäume

Einfügen mehrerer Schlüssel in binären Suchbaum:

inserts :: [Int] -> Bintree Int -> Bintree Intinserts xs t = case xs of

[] -> t( x : xss ) -> ...

Sortieren durch Einfügen in binären Suchbaum:

sort :: [Int] -> [Int]sort xs = inorder ( inserts xs Leaf )

Page 92: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Strukturelle Induktion über Bäume

zum Nachweis von Eigenschaften wie z.B.

I bt_sum (insert x t) = x + bt_sum t

I Für jeden Suchbaum t ist inorder t sortiert.I Einfügen, Löschen eines Knotens erhalten die

Suchbaum-Eigenschaft.

Page 93: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Eingeschänkte Polymorphie

reverse [1,2,3,4] = [4,3,2,1]reverse "foobar" = "raboof"reverse :: [a] -> [a]

reverse ist polymorph

Sortieren von Listen

sort [5,1,4,3] = [1,3,4,5]sort "foobar" = "abfoor"

sort :: [a] -> [a] -- ??sort [sin,cos,log] = ??

sort ist eingeschränkt polymorph

Eingeschränkte Polymorphie in Haskell durch Typklassen

Page 94: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Beispiel Sortieren/VergleichenEinfügen (in monotone Liste)

insert :: Int -> [Int] -> [Int]insert x ys = case ys of[] -> [x]y : ys’ -> if x < y then .. else ..

Sortieren durch Einfügen:

sort :: [Int] -> [Int]sort xs = case xs of[] -> []x : xs’ -> insert x (sort xs’)

Einfügen/Sortieren für beliebige Typen:mit Vergleichsfunktion lt :: a -> a -> Boolals zusätzlichem Argument

insert :: ( a -> a -> Bool ) -> a -> [a] -> [a]insert lt x ys = ... if lt x y then ...

Page 95: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Sortieren/Vergleichen

Sortieren enthält Vergleiche <

Für alle Typen a, die für die es eine Vergleichs-Funktioncompare gibt, hat sort den Typ [a] -> [a].

sort :: Ord a => [a] -> [a]

Ord ist eine Typklasse, definiert durch

class Ord a wherecompare :: a -> a -> Ordering

data Ordering = LT | EQ | GT

Page 96: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

InstanzenTypen können Instanzen von Typklassen sein.

(analog in OO: Klassen implementieren Interfaces)

Für vordefinierte Typen sind auch die meisten sinnvollenInstanzen vordefiniert

instance Ord Int ; instance Ord Char ; ...

weitere Instanzen kann man selbst deklarieren:

data Student = Student { vorname :: String, nachname :: String, matrikel :: Int}

instance Ord Student wherecompare s t =compare (matrikel s) (matrikel t)

Page 97: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Typen und Typklassen

In Haskell sind unabhängig:1. Deklaration einer Typklasse

(= Deklaration von abstrakten Methoden)class C where { m :: ... }

2. Deklaration eines Typs(= Sammlung von Konstruktoren und konkreten Methoden)data T = ...

3. Instanz-Deklaration(= Implementierung der abstrakten Methoden)instance C T where { m = ... }

In Java sind 2 und 3 nur gemeinsam möglichclass T implements C { ... }

Page 98: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Typen mit Gleichheit

class Eq a where(==) :: a -> a -> Bool(/=) :: a -> a -> Bool

Beispiele:I (’a’ == ’b’) = False

I (True /= False) = True

I ("ab" /= "ac") = True

I ([1,2] == [1,2,3]) = False

I (\ x -> 2 * x) == (\ x -> x + x) = ?

Page 99: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Typen mit totaler OrdnungInstanzen der Typklasse Eq mit

data Ordering = LT | EQ | GTclass Eq a => Ord a where

compare :: a -> a -> Ordering(<) :: a -> a -> Bool(<=) :: a -> a -> Bool(>) :: a -> a -> Bool(>=) :: a -> a -> Boolmin :: a -> a -> amax :: a -> a -> a

Beispiele:I (’a’ < ’b’) = True

I (False < True) = True

I ("ab" < "ac") = True (lexikographisch)I ([1,2] > [1,2,3]) = False

Page 100: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Klassen-Hierarchien

Typklassen können in Beziehung stehen.Ord ist „abgeleitet“ von Eq:

class Eq a where(==) :: a -> a -> Bool

class Eq a => Ord a where(<) :: a -> a -> Bool

Ord ist Typklasse mit Typconstraint (Eq)also muss man erst die Eq-Instanz deklarieren, dann dieOrd-Instanz.

Page 101: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Instanzen

data Bool = False | True

instance Eq Bool whereFalse == False = TrueTrue == True = True_ == _ = False

zu definieren:

instance Ord Bool whereFalse < True = True_ < _ = False

abgeleitet:

x <= y = ( x < y ) || ( x == y )x > y = y < xx >= y = y <= x

Page 102: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Typen mit Operation zum (zeilenweisen) Anzeigen

class Show a whereshow :: a -> String

Beispiele:I show 123 = "123"

I show True = "True"

I show [1,2] = "[1,2]"

I show (1,’a’,True) = "show (1,’a’,True)"

Instanzen Bool, Char, Int, Integer, Float,Listen und Tupel von Instanzen

Page 103: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Typklasse Show

Interpreter ghci gibt bei Eingabe exp (normalerweise)show exp aus.

Man sollte (u. a. deswegen) für jeden selbst deklariertenDatentyp eine Show-Instanz schreiben.

. . . oder schreiben lassen: deriving Show

Page 104: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Typen mit Operation zum Lesen

class Read a whereread :: String -> a

Beispiele:I ( read "3" :: Int ) = 3

I ( read "3" :: Float ) = 3.0

I ( read "False" :: Bool ) = False

I ( read "’a’" :: Char ) = ’a’

I ( read "[1,2,3]" :: [Int] ) = [1,2,3]

Instanzen Bool, Char, Int, Integer, Float,Listen und Tupel von Instanzen

Page 105: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Numerische Typen

class (Eq a, Show a) => Num a where(+) :: a -> a -> a(-) :: a -> a -> a(*) :: a -> a -> anegate :: a -> aabs :: a -> asignum :: a -> a

Beispiele:I signum (-3) = -1

I signum (-3.3) = -1.0

Instanzen Int, Integer, Float

Page 106: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Numerische Typen mit DivisionGanzzahl-Division:

class Num a => Integral a wherediv :: a -> a -> amod :: a -> a -> a

Instanzen Int, IntegerBeispiel: 3 ‘div‘ 2 = 1

Division:

class Num a => Fractional a where(/) :: a -> a -> arecip :: a -> a -> a

Instanzen: Float, Double

Beispiel: 3 / 2 = 0.6

Page 107: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Generische Instanzenclass Eq a where

(==) :: a -> a -> Bool

Vergleichen von Listen (elementweise)wenn a in Eq, dann [ a ] in Eq:

instance Eq a => Eq [a] where[] == [] = True

(x : xs) == (y : ys) = (x == y) && ( xs == ys )_ == _ = False

instance Ord a => Ord [a] wherecompare [] [] = EQcompare [] (_:_) = LTcompare (_:_) [] = GTcompare (x:xs) (y:ys) = case compare x y of

EQ -> compare xs ysother -> other

Page 108: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Abgeleitete InstanzenDeklaration eigener Typen als Instanzen von Standardklassendurch automatische Erzeugung der benötigten Methoden:

Beispiele:

data Bool = False | Truederiving (Eq, Ord, Show, Read)

data Shape = Circle Float | Rect Float Floatderiving (Eq, Ord, Show, Read)

z.B. (Circle 3 < Rect 1 2) == True

data Maybe a = Nothing | Just aderiving (Eq, Ord, Show, Read)

z.B. (Just ’a’ == Just ’b’) == False

Page 109: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Was bisher geschah

I Deklarative vs. imperative ProgrammierungI Deklarative Programmierung

Funktionale Programmierung in Haskell:I Algebraische DatentypenI Pattern MatchingI (eingeschränkte) Polymorphie, TypklassenI Rekursive Datentypen:

Peano-Zahlen, Listen, binäre BäumeI Rekursive FunktionenI strukturelle Induktion

Page 110: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Funktionen als Daten

bisher:

f :: Int -> Intf x = 2 * x + 5

äquivalent: Lambda-Ausdruck

f = \ x -> 2 * x + 5

Lambda-Kalkül: Alonzo Church 1936, Henk Barendregt 1984,. . .

Funktionsanwendung:

( \ x -> B ) A = B [ x := A ]

ist nur erlaubt, falls keine in A freie Variable durch ein λ in Bgebunden wird.

Page 111: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Der Lambda-Kalkül

. . . als weiteres Berechnungsmodell,(vgl. Termersetzungssysteme, Turingmaschine,Random-Access-Maschine)

Syntax (induktive Definition):Die Menge der Lambda-Terme Λ(X) mit Variablen aus X ist

IA: jede Variable ist ein Term: v ∈ X⇒ v ∈ Λ(X)

IS: Applikation , Funktionsanwendung:Für alle F ∈ Λ(X),A ∈ Λ(X) gilt (FA) ∈ Λ(X)

Abstraktion , Funktionsdefinition:Für alle v ∈ X,B ∈ Λ(X) gilt (λv .B) ∈ Λ(X)

Semantik: eine Relation→β auf Λ(X)(vgl.→R für Termersetzungssystem R)

Page 112: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Freie und gebundene Variablen(vorkommen)

I Das Vorkommen von v ∈ X an Position p in Term t ∈ Λ(X)heißt frei, wenn „darüber kein λv . . . . steht“

I Definition (durch strukturelle Induktion):fvar(t) = Menge der in t frei vorkommenden Variablen

I Eine Variable x heißt in A gebunden, falls A einenTeilausdruck λx .B enthält.

I bvar(t) = Menge der in t gebundenen Variablen

Beispiele:I fvar(x(λx .λy .x)) = {x},I bvar(x(λx .λy .x)) = {x , y}

Page 113: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Semantik des Lambda-Kalküls

Relation→β auf Λ(X) (ein Reduktionsschritt)

Es gilt t →β t ′, fallsI ∃p ∈ Pos(t), so daßI t [p] = (λx .B)A mit bvar(B) ∩ fvar(A) = ∅I t ′ = t [p := B[x := A]]

dabei bezeichnet B[x := A] ein Kopie von B, bei der jedesfreie Vorkommen von x durch A ersetzt ist

Ein (Teil-)Ausdruck der Form (λx .B)A heißt Redex.(Dort kann weitergerechnet werden.)

Ein Term ohne Redex heißt Normalform.(Normalformen sind Resultate von Rechnungen.)

Relation→α: gebundene Umbenennung

Page 114: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Lambda-Terme: verkürzte Notation

I Applikation als links-assoziativ auffassen, Klammernweglassen:

(. . . ((FA1)A2) . . .An) ∼ FA1A2 . . .An

Beispiel: ((xz)(yz)) ∼ xz(yz)

I geschachtelte Abstraktionen unter ein Lambda schreiben:

λx1.(λx2. . . . (λxn.B) . . . ) ∼ λx1x2 . . . xn.B

Beispiel: λx .λy .λz.B ∼ λxyz.B

Page 115: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Funktionen höherer OrdnungFunktionen als Argument von FunktionenBeispiel:

twice :: (a -> a) -> a -> atwice f x = f (f x)

Anwendung:I double hat den Typ Int -> Int

I twice double hat den Typ Int -> Int

I twice double 3hat den Typ Int und den Wert ?

I \x -> 2 * x + 1 hat den Typ Int -> Int

I twice (\x -> 2 * x + 1)hat den Typ Int -> Int

I twice (\x -> 2 * x + 1) 3hat den Typ Int und den Wert ?

I succ 0, twice succ 0, twice twice succ 0

I twice (^2) 3, twice twice (^2) 3

I Typ von twice twice ? Typ von twice twice twice ?

Page 116: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Funktionen höherer Ordnung – Beispiele

I punktweise Summe zweier Funktionen:fsum :: (a -> Int) -> (a -> Int) -> (a -> Int)fsum f g x = (f x) + (g x)fsum f g = \x -> (f x) + (g x)

Beispiele:I fsum (*2) (+1) 4,I fsum len head [ 2 .. 5 ]

I Komposition von Funktionen:(.) :: (a -> b) -> (b -> c) -> (a -> c)(f . g) x = f (g x)(f . g) = \ x -> f (g x)

Beispiele:I ( ( \ x -> x * 2 ) . len ) "foo"I suchbaum = sortiert . inorder

Page 117: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Was bisher geschah

I Deklarative vs. imperative Programmierung

Funktionale Programmierung in Haskell:I Algebraische DatentypenI Pattern MatchingI PolymorphieI TypklassenI Rekursive Datentypen:

Peano-Zahlen, Listen, BäumeI Rekursive FunktionenI strukturelle InduktionI Funktionen höherer Ordnung

(mit Funktionen als Argumenten)I λ-Kalkül, β-Reduktion

Page 118: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Wiederholung: rekursive DatentypenI Peano-Zahlendata Nat = Z

| S Nat

I Listendata List a = Nil {}

| Cons { head :: a, tail :: List a}

oder kürzerdata [a] = [] | a : [a]

I Binärbäumedata Tree a = Leaf {}

| Branch { left :: Tree a,key :: a,right :: Tree a}

oder kürzerdata Tree a = Leaf

| Branch ( Tree a ) a ( Tree a )

Page 119: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Wiederholung: Funktionen auf rekursiven DatentypenEntwurf rekursiver Funktionen auf rekursiven Datentypen:

1. Typdefinition2. Angabe aller Basis- und rekursiven Fälle3. Definition der Ergebnisse der Basisfälle4. Definition der Ergebnisse der rekursiven Fälle5. evtl. Typ verallgemeinern

Beispiel: Summe aller Schlüssel eines Baumes

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

1. Typdefinition: tsum :: Tree Int -> Int2. Angabe aller Basis- und rekursiven Fälle:

tsum t = case t ofLeaf -> ...Branch l k r -> ...

3. Definition der Ergebnisse der Basisfälle: Leaf -> 04. Definition der Ergebnisse der rekursiven Fälle:

Branch l k r -> (tsum l) + k + (tsum r)

Page 120: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Wiederholung: Funktionen auf Listen und Bäumen

Operationen auf Listen:I Verdoppeln jedes ListenelementsI Angabe gerade / ungerade für jedes ListenelementI Länge der ListeI Summe aller Listenelemente

Operationen auf Bäumen:I Verdoppeln jedes SchlüsselsI Angabe gerade / ungerade für jeden SchlüsselI Anzahl aller SchlüsselI Summe aller SchlüsselI Inorder-Durchquerung

Page 121: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Wiederholung: Funktionen auf ListenBeispiel: Verdoppeln jedes Elementes in einer Liste

double :: Int -> Intdouble x = x + xdoubles :: [Int] -> [Int]doubles xs = case xs of

[] -> [](y:ys) -> (double y) : (doubles ys)

oder mit anonymer Funktion (λ-Notation):

doubles :: [Int] -> [Int]doubles xs = case xs of

[] -> [](y:ys) -> ((\ x -> x + x) y) : (doubles ys)

evens :: [Int] -> [Bool]evens xs = case xs of

[] -> [](y:ys) -> ((\x->(mod x 2 == 0)) y) : (evens ys)

Page 122: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Rekursionsmuster für Listen

gemeinsame Eigenschaft:Ergebnis ist die Liste der Funktionswerte jedes Elementes derEingabeliste

I Parameter:I auf jedes Element anzuwendende Funktion h :: a -> bI Liste vom Typ [a]

I Ergebnis: Liste vom Typ [b]

I Berechnung (Pattern Matching):f xs = case xs of

[] -> [](x : xss) -> ( h x ) : ( f xss )

Page 123: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Rekursionsmuster mapBeschreibung des Rekursionsschemas

f x = case x of[] -> [](x : xss) -> ( h x ) : ( f xss )

durch eine Funktion höherer Ordnungmit der Funktion h :: a -> b als Argument

map :: ( a -> b ) -> [a] -> [b]

Anwendung: f = map h

ermöglicht kurze Funktionsdefinition, z.B.

doubles :: [ Int ] -> [ Int ]doubles = map double

oder mit anonymer Funktion: doubles = map (\z -> z*2)

oder noch kürzer: doubles = map ( *2 )

Page 124: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

filterBeispiel: nur gerade Zahlen der Eingabeliste

ev :: Int -> Boolev = \x -> ( mod x 2 == 0 )

evens :: [Int] -> [Int]evens xs = case xs of

[] -> []( x : xss ) -> if ev x

then x : ( evens xss )else ( evens xss )

Funktion höherer Ordnung:

filter :: ( a -> Bool ) -> [a] -> [a]filter p xs = case xs of

[] -> []( x : xss ) -> if ( p x )

then x : ( filter p xss )else filter p xss

Page 125: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

filter

ev :: Int -> Boolev = \x -> ( mod x 2 == 0 )

filter :: (a -> Bool) -> [a] -> [a]filter p xs = case xs of

[] -> []( x : xss ) -> if ( p x )

then x : ( filter p xss )else filter p xss

ermöglicht kurze Funktionsdefinitionen, z.B.:

evens = filter ev

oder mit anonymer Funktion

evens = filter ( \x -> ( mod x 2 == 0 ) )

filter ( < 100 ) ( map ( ^2 ) [ 0, 2 .. 10 ] )

Page 126: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Mehr rekursive Funktionen auf Listen

data [a] = [] | a : [a]

Länge einer Liste:

len :: [a] -> Intlen xs = case xs of

[] -> 0( _ : xss ) -> 1 + (len xss)

Summe aller Listenelemente:

sum :: [Int] -> Intsum xs = case xs of

[] -> 0( x : xss ) -> x + (sum xss)

Page 127: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Mehr Rekursionsmuster für Listen

gemeinsame Eigenschaft:

I Parameter:I Wert nil :: b für leere EingabelisteI Funktion cons :: a -> b -> b

zur Berechnung eines Wertes aus dem bisher berechnetenWert und einem Listenelement

I Liste vom Typ [a]

I Ergebnis vom Typ b

I Berechnung (Pattern Matching):f xs = case xs of

[] -> nil(x : xss) -> cons x ( f xss )

Page 128: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Rekursionschema fold

Funktion höherer Ordnung (mit Funktionen als Argumenten)

fold :: b -> (a -> b -> b) -> [a] -> bfold nil cons xs = case xs of

[] -> nilx : xss -> cons x ( fold nil cons xss )

ermöglicht kurze Funktionsdefinition, z.B.

len = fold 0 (\ x y -> 1 + x)sum = fold 0 (\ x y -> x + y)and = fold True (&&)

oder kurz: sum = fold 0 (+)

Page 129: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Funktionen höherer Ordnung für Listen

in Haskell vordefinierte Funktionen höherer Ordnung

I zur Verarbeitung von Listen:map :: (a -> b) -> [a] -> [b]foldr :: (a -> b -> b) -> b -> [a] -> bfilter :: (a -> Bool) -> [a] -> [a]takeWhile :: (a -> Bool) -> [a] -> [a]partition :: (a -> Bool) -> [a] -> ([a],[a])

I zum Vergleichen, Ordnen:nubBy :: (a -> a -> Bool) -> [a] -> [a]data Ordering = LT | EQ | GTminimumBy:: (a -> a -> Ordering) -> [a] -> a

Page 130: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Rekursionsschemata über Bäumedata Tree a = Leaf| Branch { left :: Tree a, key :: a, right :: Tree a }

doubles :: Tree Int -> [Int]doubles t = case t of

Leaf -> LeafBranch l k r -> Branch (doubles l) (k*2) (doubles r)

preorder :: Tree a -> [a]preorder t = case t of

Leaf -> []Branch l k r -> [ k ]

++ ( preorder l )++ ( preorder r )

sum :: Tree Int -> Intsum t = case t of

Leaf -> 0Branch l k r -> ( sum l ) + k + ( sum r )

Page 131: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Rekursionsschema map über Bäumef :: Tree a -> bf t = case t of

Leaf -> leafBranch l k r -> branch (f l) (g k) (f r)

Beispiel:

f = doublesg = double

Rekursionsschema:

tmap :: (a -> b ) -> ( Tree a ) -> ( Tree b )tmap f t = case t of

Leaf -> LeafBranch l k r -> Branch (tmap f l)

(f k)(tmap f r)

doubles = tmap ( 2* )

Page 132: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Rekursionsschema fold über Bäume

f :: Tree a -> bf t = case t of

Leaf -> leafBranch l k r -> branch (f l) k (f r)

Beispiel:

f = preorderleaf = []branch l’ k r’ = [k] ++ l’ ++ r’

Rekursionsschema:

tfold :: b -> (b -> a -> b -> b) -> (Tree a) -> btfold leaf branch t = case t of

Leaf -> leafBranch l k r -> branch (tfold leaf branch l)

k(tfold leaf branch r)

Page 133: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Beispiele: fold über Bäume

tfold :: b -> (b -> a -> b -> b) -> (Tree a) -> btfold leaf branch t = case t of

Leaf -> leafBranch l k r -> branch (tfold leaf branch l)

k(tfold leaf branch r)

preorder = tfold [] ( \ l’ k r’ -> [k] ++ l’ ++ r’ )sum = tfold 0 ( \ l’ k r’ -> l’ + k + r’ )

analog: Anzahl der Blätter, inneren Knoten, Tiefe

Page 134: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Rekursionsmuster (Merksätze)

Rekursionsmuster anwenden =jeden Konstruktor durch eine passende Funktion ersetzen

I Anzahl der Muster-Argumente =Anzahl der Konstruktoren(plus eins für das Datenargument)

I Stelligkeit eines Muster-Argumentes =Stelligkeit des entsprechenden Konstruktors

I Rekursion im Typ→ Rekursion im MusterI zu jedem rekursiven Datentyp gibt es genau ein

passendes Rekursionsmuster

Page 135: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Was bisher geschahFunktionale Programmierung in Haskell:

I Algebraische DatentypenI Pattern MatchingI PolymorphieI TypklassenI Rekursive Datentypen: Peano-Zahlen, Listen, BäumeI Rekursive FunktionenI strukturelle InduktionI Rekursionsschemata für Peano-Zahlen, Listen, BäumeI Funktionen höherer Ordnung

(mit Funktionen als Argumenten)I λ-Kalkül, β-ReduktionI fold auf rekursiven Datentypen

(Peano-Zahlen, Listen, Bäume)I map auf Listen und Bäumen, filter auf Listen

Page 136: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Nützliche Funktionentake :: Int -> [ a ] -> [ a ]take 0 _ = []take _ [] = []take n ( x : xs ) = x : ( take ( n - 1 ) xs )

take 3 [ 1 .. 10 ]

takeWhile :: ( a -> Bool ) -> [ a ] -> [ a ]takeWhile p xs = case xs of

[] -> []x : xss -> if p x

then x : ( take While p xss )else []

takeWhile ( \ x -> mod x 5 < 4) [ 1 .. 10 ]

dropWhile :: ( a -> Bool ) -> [ a ] -> [ a ]dropWhile p xs = case xs of

[] -> []x : xss -> if p x

then ( dropWhile p xss )else xss

dropWhile ( < 4 ) [ 1 .. 10 ]

Page 137: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Nützliche Funktionen

zip :: [ a ] -> [ b ] -> [ ( a , b ) ]zip ( x : xs ) ( y : ys )

= ( x, y ) : zip ( xs ) ( ys )zip _ _ = []

zip "foo" [1 .. 5]

zipWith :: ( a -> b -> c )-> [ a ] -> [ b ] -> [ c ]

zipWith f xs ys = map ( \ ( x, y ) -> f x y )( zip xs ys )

zipWith (+) [ 1 .. 10 ] [ 2, 4 .. 10 ]

zipWith (\x y -> ( foldr (\ _ y -> 1 + y) 0 x) + y)[ "foo", "b", "ar" ] [ 1 .. 10 ]

Page 138: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Wiederholung – Auswertung von Ausdrücken

Reduktion: Termersetzung durch FunktionsanwendungRedex: reduzierbarer Teilterm

Normalform: nicht-reduzierbarer Ausdruck(Ausdruck ohne Redex)

Auswertung: schrittweise Reduktion, bis Normalform erreicht

square :: Int -> Intsquare x = x * x

2 Möglichkeiten,den Wert von square (3 + 1) zu berechnen

Es wird bei beiden Möglichkeiten derselbe Wert berechnet.(Haskell ist nebenwirkungsfrei.)

Page 139: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Auswertungsreihenfolge

mult :: Int -> Int -> Intmult = \x y -> x * y

Redexe von

mult ( 1 + 2 ) ( 2 + 3 )

data N = Z | S Nnichtnull :: N -> Boolnichtnull n = case n of

Z -> FalseS _ -> True

Redexe von

nichtnull ( S undefined )

Page 140: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Auswertungs-Strategieninnermost Reduktion von Redexen, die keinen Redex

enthalten(Parameterübergabe by value)

outermost Reduktion von Redexen, die in keinem Redexenthalten sind(Parameterübergabe by name)

(jeweils so weit links wie möglich zuerst)

square :: Int -> Intsquare x = x * x

square (3 + 1)

Teilterme in λ-Ausdrücken werden nicht reduziert.

(\ x -> 1 + 2) 1

Page 141: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Termination

inf :: Intinf = 1 + inf

fst :: ( a , b ) -> afst ( x, y ) = x

Auswertung von

fst (3, inf)

terminiert unter outermost-Strategie,aber nicht unter innermost-Strategie

SatzFür jeden Ausdruck, für den die Auswertung unter irgendeinerStrategie terminiert, terminert auch die Auswertung unteroutermost-Strategie.

Page 142: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Unendliche Datenstrukturen

nats_from :: Int -> [ Int ]nats_from n = n : ( nats_from ( n + 1 ) )

nats_from 3

outermost-Auswertung von

head ( tail ( tail ( nats_from 3 ) )

= head ( tail ( tail ( 3 : ( nats_from ( 3 + 1 )))))= head ( tail ( nats_from (3 + 1)))= head ( tail ( (3 + 1) : nats_from (( 3 + 1 ) + 1 ))= head ( nats_from ( ( 3 + 1 ) + 1 ) )= head (((3 + 1) + 1) : nats_from (((3 + 1) + 1) + 1))= ( 3 + 1 ) + 1= 4 + 1= 5

Page 143: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Lazyness

I jeder Wert wird erst bei Bedarf ausgewertet.I Listen sind Streams, der Tail wird erst bei Bedarf

ausgewertet.I Wann die Auswertung stattfindet, lässt sich nicht

beobachten.

Die Auswertung hat keine Nebenwirkungen.

Page 144: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Strictness

zu jedem Typ T betrachte T⊥ = {⊥} ∪ T

dabei ist ⊥ ein „Nicht-Resultat vom Typ T “I Exception undefined :: T

I oder Nicht-Termination let { x = x } in x

Definition:Funktion f heißt strikt, wenn f (⊥) = ⊥.Funktion f mit n Argumenten heißt strikt in i , falls(xi = ⊥)⇒ f (x1, . . . , xn) = ⊥

in Haskell:I Konstruktoren (Cons,. . . ) sind nicht strikt,I Destruktoren (head, tail,. . . ) sind strikt.

Page 145: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Strictness – Beispiele

I length :: [a] -> Int ist strikt:length undefined ==> exception

I (:) :: a->[a]->[a] ist nicht strikt im 1. Argument:

length (undefined : [2,3]) ==> 3

d.h. (undefined : [2,3]) ist nicht ⊥I (&&) ist strikt im 1. Argument,

nicht strikt im 2. Argumentundefined && True ==> (exception)False && undefined ==> False

Page 146: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Lazy Evaluation – Realisierung

Begriffe:nicht strikt : nicht zu früh auswerten

lazy : höchstens einmal auswerten

bei jedem Konstruktor- und Funktionsaufruf:I kehrt sofort zurückI Resultat ist thunkI thunk wird erst bei Bedarf ausgewertetI Bedarf entsteht durch Pattern MatchingI nach Auswertung: thunk durch Resultat überschreiben

Lazy Evaluation (Bedarfsauswertung) =Outermost-Reduktionsstrategie mit Sharing

Page 147: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Unendliche Datenstruktureninf :: Intinf = 1 + inf

fst(3, inf)

einsen :: [Int]einsen = 1 : einsen

head einsentake 3 einsen

walzer :: [Int]walzer = 1 : 2 : 3 : walzer

nats :: [Int]nats = 0 : map (+1) nats

takeWhile (<= 5) nats

Liste aller Quadratzahlen? Primzahlen?

Page 148: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Motivation: Datenströme

Folge von Daten:I erzeugen (producer)I transformierenI verarbeiten (consumer)

aus softwaretechnischen Gründen:diese drei Aspekte im Programmtext trennen,

aus Effizienzgründen:in der Ausführung verschränken

(bedarfsgesteuerte Transformation/Erzeugung)

Page 149: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Rekursive Stream-Definitionennats = 0 : map (+1) nats

fibonacci = 0: 1: zipWith (+) fibonacci ( tail fibonacci )

take 10 fibonaccitake 1 $ dropWhile (< 200) fibonacci

Welchen Wert hat bin ?

bin = False: True: concat ( map ( \ x -> [ x, not x ] )

( tail bin ) )

Thue-Morse-Folge t = 0110100110010110 . . .mit vielen interessanten Eigenschaften, z.B.

I t := limn→∞ τn(0) für τ : 0 7→ 01,1 7→ 10I t ist kubikfreiI Abstandsfolge v := 210201210120 . . .

ist auch Fixpunkt eines Morphismus, quadratfrei

Page 150: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Primzahlen

Sieb des Eratosthenes

nats_from :: Int -> [ Int ]nats_from n = n : nats_from ( n + 1 )

primzahlen :: [ Int ]primzahlen = sieb $ nats_from 2

sieb :: [ Int ] -> [ Int ]sieb (x : xs) = ...

take 100 primzahlentakeWhile (< 100) primzahlen

Page 151: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Was bisher geschahFunktionale Programmierung in Haskell:

I Algebraische DatentypenI Pattern MatchingI PolymorphieI TypklassenI Rekursive Datentypen: Peano-Zahlen, Listen, BäumeI Rekursive FunktionenI strukturelle InduktionI Rekursionsschemata für Peano-Zahlen, Listen, BäumeI Funktionen höherer Ordnung

(mit Funktionen als Argumenten)I λ-Kalkül, β-ReduktionI fold auf rekursiven Datentypen

(Peano-Zahlen, Listen, Bäume)I map auf Listen und Bäumen, filter auf ListenI Bedarfsauswertung (lazy evaluation):

leftmost outermost reduction + sharing

Page 152: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Sortieren

sortiert :: Ord a => [a] -> Boolsortiert xs = foldr (&&) True

$ zipWith (<=) xs $ tail xs

sort :: Ord a => [a] -> [a]

z.B. durchI Einfügen in (anfangs leeren) binären SuchbaumI Inorder-Ausgabe

Page 153: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Klassische Sortier-Verfahren

I Sortieren durch Einfügeninsert :: Ord a => a -> [ a ] -> [ a ]insert x [] = [x]insert x ( y : ys ) | x <= y = x : y : ys

| x > y = y : (insert x ys)

isort :: Ord a => [a] -> [a]isort [] = []isort (x:xs) = insert x $ isort xs

I Quicksortqsort :: Ord a => [a] -> [a]qsort [] = []qsort (x:xs) = qsort [ y | y <- xs, y <= x]

++ [x] ++ qsort [ y | y <- xs, y > x]

Page 154: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Mergesort

merge :: Ord a => [a] -> [a] -> [a]merge xs [] = xsmerge [] ys = ysmerge (x : xs) (y : ys)

| x <= y = x : merge xs ( y : ys )| otherwise = y : merge ( x : xs ) ys

msort :: Ord a => [a] -> [a]msort [] = []msort [ x ] = [ x ]msort xs = merge ( msort l ) ( msort r )where ( l , r ) = splitAt halb xs

halb = div (length xs) 2

Page 155: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Ver- und EntschlüsselnVerschiebe-Chiffre

I symmetrisches Verschlüsselungs-Verfahren:derselbe Schlüssel zum Ver- und Entschlüsseln

I Substitutionschiffre: Ersetzung jedes Klartextsymbolesdurch ein Chiffretextsymbol

I monoalphabetisch: Klartextsymbol überall durch dasselbeChiffretextsymbol ersetzt

Klartextmenge: M = {a,b, . . . , z}∗

Chiffretextmenge: C = {a,b, . . . , z}∗

Schlüsselmenge: K = {0, . . . ,25}Verschlüsselung: jeden Buchstaben durch Buchstaben k

Positionen später im Alphabet ersetzenEntschlüsselung: jeden Buchstaben durch Buchstaben k

Positionen früher im Alphabet ersetzen

klassisches Beispiel: Caesar-Chiffre k = 3

Page 156: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Verschlüsselnfür jeden (Klein-)Buchstaben im Klartext:

I Buchstabe durch Zahl ∈ {0, . . . ,25} ersetzen

b2int :: Char -> Intb2int b = ord b - ord ’a’

I Zahl durch entsprechenden Buchstaben ersetzen

int2b :: Int -> Charint2b n = chr (ord ’a’ + n)

I Buchstabe mit Schlüssel k verschlüsseln:

enc :: Int -> Char -> Charenc k b | isLower b = int2b ( mod (k + b2int b) 26)

| otherwise = b

Klartext verschlüsseln:

encode :: Int -> String -> Stringencode k = map ( enc k )

Chiffretext entschlüsseln: . . .

Page 157: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Angriffe auf Verschiebechiffren

Ciphertext-Only-Angriffe auf Verschiebechiffren

gegeben: verschlüsselter TextI hinreichend lang,I natürlichsprachig (deutsch),I mit Verschiebechiffre verschlüsselt

gesucht: Klartext ( und evtl. Schlüssel )

Ideen für Angriffe:I Brute Force: Ausprobieren aller 26 SchlüsselI typische Häufigkeiten von Buchstaben,

Buchstabengruppen

Page 158: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Funktionen auf Listen / Strings

Anzahl der Vorkommen eines Elementes in einer Liste:

countEl :: Eq a => a -> [ a ] -> IntcountEl b = ( foldr (\x y -> y + 1) 0 )

. filter ( == b )

z.B. countEl ’o’ "foo" = 2

Anzahl der Kleinbuchstaben in einer Zeichenkette:

lowers :. String -> Intlowers = ( foldr (\x y -> y + 1) 0 )

. filter ( isLower )

z.B. lowers "Foo !" = 2

Page 159: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Funktionen auf Listen / Strings

alle Positionen eines Elementes in einer Liste:

positions :: Eq a => a -> [ a ] -> [ Int ]positions x xs = ( map fst )

$ filter (\ ( _ , y) -> y == x )$ zip [ 0 .. ] xs

z.B. positions ’o’ "foo" = [1,2]

Rotieren von Listen

rotate :: Int -> [ a ] -> [ a ]rotate n xs = drop n xs ++ take n xs

Page 160: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Buchstaben-HäufigkeitenHäufigkeiten (in deutschen Texten):

haeufigkeitstabelle :: [ Float ]haeufigkeitstabelle = [6.51, 1.89, 3.06, 5.08,17.4, 1.66, 3.01, 4.76, 7.55, 0.27, 1.21,3.44, 2.53, 9.78, 2.51, 0.79, 0.02, 7.00,7.27, 6.15, 4.35, 0.67, 1.89, 0.03, 0.04,1.13]

zip [’a’ .. ’z’] häufigkeitstabelle

proz :: Int -> Int -> Floatproz m n = (fromIntegral m / fromIntegral n) * 100

Prozentuale Häufigkeit im (verschlüsselten) Text:

häufigkeiten :: String -> [ Float ]häufigkeiten t = [ proz ( countEl x t ) n |

x <- [ ’a’ .. ’z’ ] ]where n = lowers t

Page 161: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

StatistikTest auf (annähernd) gleiche Verteilung durchChi-Quadrat-Test für Buchstabenhäufigkeiten

I erwartet: e ∈ R{0,...,25}≥0

(häufigkeitstabelle)I im Text t aufgetreten: a ∈ R{0,...,25}

≥0(häufigkeiten t)

∀e,a ∈ R{0,...,25}≥0 : χ2(a,e) =

n−1∑i=0

(ai − ei)2

ei

chiquad :: [ Float ] -> [ Float ] -> Floatchiquad a e = foldr (\x y -> x + y) 0

$ zipWith (\ x y -> (x - y)^2 / y) a e

chiquad (häufigkeiten "ipiqirx") häufigkeitstabelle

Page 162: Deklarative Programmierung - imn.htwk-leipzig.deschwarz/lehre/ss15/dp/fop15-folien.pdf · Programmierparadigmen Abstraktionsstufen (zeitliche Entwicklung): I Programm = Maschinencode

Knacken der VerschiebechiffreChi-Test für alle möglichen Schlüssel k ∈ {0, . . . ,25} für Chiffretext c:

chitab = [ chiquad ( rotate k ( häufigkeiten c ) )häufigkeitstabelle| k <- [ 0 .. 25 ] ]

Index (Verschiebung) des kleinsten χ2-Wertes:

k = head ( positions (minimum chitab ) chitab )where chitab = [ chiquad (rotate n (häufigkeiten c))

häufigkeitstabelle| n <- [ 0 .. 25 ] ]

ist (wahrscheinlich) der Schlüssel

crack :: String -> Stringcrack c = decode k c

where k = head ( positions (minimum chitab ) chitab )chitab = [ chiquad (rotate n (häufigkeiten c))

häufigkeitstabelle| n <- [0 .. 25]]