Praktische Informatik 3
Einf¨ uhrung in die Funktionale Programmierung
Christoph L¨uth
WS 08/09
Christoph L¨uth: Praktische Informatik 3 0 WS 08/09
Vorlesung vom 29.10.2008:
Einf¨ uhrung
Christoph L¨uth: Praktische Informatik 3 1 WS 08/09
Personal
Vorlesung: Christoph L¨uth<cxl>, Cartesium 2.046, Tel. 64223 Tutoren: Dominik Luecke<luecke>
Klaus Hartke<hartke>
Marcus Ermler<maermler>
Christian Maeder<maeder Ewaryst Schulz & Dominik Dietrich Fragestunde: Berthold Hoffmann<hof>
Website:www.informatik.uni-bremen.de/~cxl/lehre/pi3.ws08.
Christoph L¨uth: Praktische Informatik 3 2 WS 08/09
Termine
Vorlesung:
Mi 13 – 15, SFG 0140 Tutorien:
Di 10 – 12 MZH 7210 Klaus Hartke 17 – 19 MZH 1380 Marcus Ermler
Mi 8 – 10 MZH 7250 Ewaryst Schulz & Dominik Dietrich Do 8 – 10 FZB 0240 Dominik Luecke
10 – 12 Cart 0.01 Christian Maeder Fragestunde(FAQ):
Mi 10 – 12 Berthold Hoffmann (Cartesium 2.048)
Christoph L¨uth: Praktische Informatik 3 3 WS 08/09
Ubungsbetrieb ¨
Ausgabe der ¨Ubungsbl¨atter ¨uber die WebseiteMontag vormittag Besprechung der ¨Ubungsbl¨atter in den Tutorien
Bearbeitungszeitzwei Wochen
Abgabeelektronisch bis Montag um 10:00 SechsUbungsbl¨¨ atter (und ein Bonusblatt)
Ubungsgruppen: max.¨ drei Teilnehmer(nur in Ausnahmef¨allen vier)
Christoph L¨uth: Praktische Informatik 3 4 WS 08/09
Scheinkriterien — Vorschlag:
Alle ¨Ubungsbl¨attersind zu bearbeiten.
Pro ¨Ubungsblattmind. 50% aller Punkte
Es gibt einBonus¨ubungsblatt, um Ausf¨alle zu kompensieren.
Pr¨ufungsgespr¨ach(Individualit¨at der Leistung)
Christoph L¨uth: Praktische Informatik 3 5 WS 08/09
Spielregeln
Quellen angebenbei
Gruppen¨ubergreifenderZusammenarbeit;
Internetrecherche, Literatur, etc.
ErsterT¨auschungsversuch:
NullPunkte
ZweiterT¨auschungsversuch:Kein Schein.
Deadline verpaßt?
Vorherank¨undigen, sonstnullPunkte.
Fahrplan
Teil I: Grundlagen
Rekursion als Berechnungsmodell Rekursive Datentypen, rekursive Funktionen Typvariablen und Polymorphie
Funktionen h¨oherer Ordnung
Funktionaler Entwurf, Standarddatentypen Teil II: Abstraktion
Teil III: Beispiele, Anwendungen, Ausblicke
Warum funktionale Programmierung lernen?
Denken inAlgorithmen, nicht inProgrammiersprachen Abstraktion:Konzentration auf das Wesentliche WesentlicheElemente moderner Programmierung:
DatenabstraktionundFunktionale Abstraktion Modularisierung
TypisierungundSpezifikation
Blick ¨uber den Tellerrand — Blick in die Zukunft Studium6= Programmierkurs — was kommt in 10 Jahren?
Christoph L¨uth: Praktische Informatik 3 8 WS 08/09
Geschichtliches
Grundlagen1920/30
Kombinatorlogik undλ-Kalk¨ul (Sch¨onfinkel, Curry, Church) ErsteProgrammiersprachen1960
LISP(McCarthy),ISWIM(Landin) WeitereProgrammiersprachen 1970– 80
FP(Backus);ML(Milner, Gordon), sp¨aterSMLundCAML;Hope (Burstall);Miranda(Turner)
Konsolidierung1990
CAML,Formale Semantikf¨ur Standard ML HaskellalsStandardsprache
Christoph L¨uth: Praktische Informatik 3 9 WS 08/09
Referentielle Transparenz
Programme als Funktionen
P:Eingabe→Ausgabe
Keine ver¨anderlichenVariablen— kein versteckterZustand
R¨uckgabewert h¨angt ausschließlich von Werten der Argumente ab, nicht vom Aufrufkontext (referentielle Transparenz)
AlleAbh¨angigkeiten explizit
Christoph L¨uth: Praktische Informatik 3 10 WS 08/09
Programmieren mit Funktionen
Programmewerden durchGleichungendefiniert:
inc x = x+ 1 addDouble x y = 2*(x+ y)
Auswertung durchReduktionvonAusdr¨ucken:
addDouble (inc 5) 4 2*(inc 5+ 4) 2*((5+1)+ 4) 20 Nichtreduzierbare Ausdr¨ucke sindWerte
VorgebeneneBasiswerte:Zahlen,Zeichen DefinierteDatentypen:Wahrheitswerte,Listen, . . .
Christoph L¨uth: Praktische Informatik 3 11 WS 08/09
Definition von Funktionen
Zwei wesentlicheKonstrukte:
Fallunterscheidung Rekursion Beispiel:
fac n = if n == 0 then 1 else n * (fac (n-1)) Auswertung kanndivergieren!
Christoph L¨uth: Praktische Informatik 3 12 WS 08/09
Imperativ vs. Funktional
ImperativeProgrammierung:
Zustands¨ubergangΣ→Σ, Lesen/Schreiben von Variablen Kontrollstrukturen: Fallunterscheidung if. . .then. . .else
Iteration while. . . FunktionaleProgrammierung:
Funktionenf:E→A
Kontrollstrukturen: Fallunterscheidung Rekursion
Christoph L¨uth: Praktische Informatik 3 13 WS 08/09
Nichtnumerische Werte
Rechnen mitZeichenketten
repeat n s == if n == 0 then ""
else s ++ repeat (n-1) s Auswertung:
repeat 2 "hallo "
"hallo" ++ repeat 1 "hallo"
"hallo "++ ("hallo " ++ repeat 0 "hallo ")
"hallo "++ ("hallo " ++ "")
"hallo "++ "hallo "
"hallo hallo "
Christoph L¨uth: Praktische Informatik 3 14 WS 08/09
Typisierung
Typenunterscheiden Arten von Ausdr¨ucken:
repeat n s =. . . n Zahl s Zeichenkette VerschiedeneTypen:
Basistypen(Zahlen, Zeichen) strukturierte Typen(Listen, Tupel, etc) WozuTypen?
Typ¨uberpr¨ufungw¨ahrendUbersetzung¨ erspartLaufzeitfehler Programmsicherheit
Christoph L¨uth: Praktische Informatik 3 15 WS 08/09
Signaturen
Jede Funktion hat eineSignatur fac :: Int-> Int
repeat :: Int-> String-> String Typ¨uberpr¨ufung
facnur aufIntanwendbar, Resultat istInt
repeatnur aufIntundStringanwendbar, Resultat istString
Christoph L¨uth: Praktische Informatik 3 16 WS 08/09
Ubersicht: Typen in Haskell ¨
Ganze Zahlen Int 0 94 -45
Fließkomma Double 3.0 3.141592
Zeichen Char ’a’ ’x’ ’\034’ ’\n’
Zeichenketten String "yuck" "hi\nho\"\n"
Wahrheitswerte Bool True False
Listen [a] [6, 9, 20]
["oh", "dear"]
Tupel (a, b) (1, ’a’) (’a’, 4)
Funktionen a-> b
Christoph L¨uth: Praktische Informatik 3 17 WS 08/09
Auswertungsstrategien
Vonaußennachinnen(outermost-first):
inc (addDouble (inc 3) 4) (addDouble (inc 3) 4)+ 1 2*(inc 3+ 4)+ 1
2*(3+ 1+ 4)+ 1 2*8+1 17
Voninnennachaußen(innermost-first):
inc (addDouble (inc 3) 4) inc (addDouble (3+ 1) 4) inc (2*((3+ 1)+ 4)) (2*((3+ 1)+ 4))+ 1
2*8+1 17
Christoph L¨uth: Praktische Informatik 3 18 WS 08/09
Auswertungsstrategien
Outermost-first entsprichtcall-by-need,verz¨ogerteAuswertung.
Innermost-first entsprichtcall-by-value,strikteAuswertung Beispiel:
div :: Int-> Int-> Int
Ganzzahlige Division, undefiniert f¨urdiv n 0 mult :: Int-> Int-> Int
mult n m = if n == 0 then 0 else (mult (n- 1) m)* m Auswertung vonmult 0 (div 1 0)
Christoph L¨uth: Praktische Informatik 3 19 WS 08/09
Striktheit
Def: Funktionf iststriktgdw.
Ergebnis ist undefiniert sobald ein Argument undefiniert ist Standard ML, Java, C etc. sindstrikt
Haskell istnicht-strikt
Fallunterscheidung istimmernicht-strikt
Christoph L¨uth: Praktische Informatik 3 20 WS 08/09
Zusammenfassung
ProgrammesindFunktionen, definiert durchGleichungen Referentielle Transparenz
kein impliziter Zustand, keine ver¨anderlichen Variablen Ausf¨uhrungdurchReduktionvon Ausdr¨ucken
Auswertungsstrategien,Striktheit Typisierung:
Basistypen: Zahlen, Zeichen(ketten), Wahrheitswerte Strukturierte Typen: Listen, Tupel
Jede Funktionfhat eine Signaturf :: a-> b
Christoph L¨uth: Praktische Informatik 3 21 WS 08/09
Vorlesung vom 05.11.2008:
Funktionen und Datentypen
Organisatorisches
Tutorien: Ungleichverteilung Di 10– 12: 42 Mi 8 – 10: 32 Do 10– 12: 26 Di 17– 19: 18 Do 8– 10: 10 Ubungsbl¨¨ atter:
L¨osungen in LATEX (siehe Webseite)
Fahrplan
Teil I: Grundlagen
Rekursion als Berechnungsmodell Rekursive Datentypen, rekursive Funktionen Typvariablen und Polymorphie
Funktionen h¨oherer Ordnung
Funktionaler Entwurf, Standarddatentypen Teil II: Abstraktion
Teil III: Beispiele, Anwendungen, Ausblicke
Christoph L¨uth: Praktische Informatik 3 24 WS 08/09
Inhalt
Definition vonFunktionen SyntaktischeFeinheiten Definition vonDatentypen
Aufz¨ahlungen Produkte
Rekursive Datentypen Basisdatentypen:
Wahrheitswerte numerische Typen alphanumerische Typen
Christoph L¨uth: Praktische Informatik 3 25 WS 08/09
Wie definiere ich eine Funktion?
Generelle Form:
Signatur:
max :: Int-> Int-> Int Definition
max x y = if x < y then y else x Kopf, mit Parametern
Rumpf(evtl. l¨anger, mehrere Zeilen)
TypischesMuster: Fallunterscheidung, dann rekursiver Aufruf Was geh¨ort zum Rumpf (Geltungsberereich)?
Christoph L¨uth: Praktische Informatik 3 26 WS 08/09
Die Abseitsregel
Funktionsdefinition:
f x1x2. . .xn=E
Geltungsbereichder Definition vonf:
alles, was gegen¨uberfeinger¨ucktist.
Beispiel:
f x = hier faengts an und hier gehts weiter
immer weiter
g y z = und hier faengt was neues an Gilt auchverschachtelt.
Kommentare sindpassiv
Christoph L¨uth: Praktische Informatik 3 27 WS 08/09
Kommentare
Pro Zeile: Ab--bis Ende der Zeile
f x y = irgendwas -- und hier der Kommentar!
Uber mehrere Zeilen: Anfang¨ {-, Ende-}
{-
Hier f¨angt der Kommentar an erstreckt sich ¨uber mehrere Zeilen
bis hier -}
f x y = irgendwas Kann geschachtelt werden.
Christoph L¨uth: Praktische Informatik 3 28 WS 08/09
Bedingte Definitionen
Statt verschachtelter Fallunterscheidungen . . . f x y = if B1 then P else
if B2 then Q else ...
. . .bedingte Gleichungen:
f x y
| B1 = ...
| B2 = ...
Auswertung der Bedingungen von oben nach unten Wenn keine Bedingung wahr ist:Laufzeitfehler! Deshalb:
| otherwise = ...
Christoph L¨uth: Praktische Informatik 3 29 WS 08/09
Lokale Definitionen
Lokale Definitionen mitwhereoderlet:
f x y
| g = P y
| otherwise = Q where y = M
f x = N x
f x y = let y = M
f x = N x in if g then P y
else Q f,y, . . . werdengleichzeitigdefiniert (Rekursion!) Namenf,yund Parameter (x)¨uberlagernandere Es gilt dieAbseitsregel
Deshalb:Aufgleiche Einr¨uckungder lokalen Definition achten!
Christoph L¨uth: Praktische Informatik 3 30 WS 08/09
Datentypen und Funktionen
Datentypen konstruierenWerte
Funktionen sindBerechnungen
Konstruktion f¨ur Datentypen←→Definition von Funktionen
Christoph L¨uth: Praktische Informatik 3 31 WS 08/09
Aufz¨ ahlungen
Aufz¨ahlungen: Menge vondisjunktenKonstanten Days={Mon,Tue,Wed,Thu,Fri,Sat,Sun}
Mon6=Tue,Mon6=Wed,Tue6=Thu,Wed6=Sun. . .
GenausiebenunterschiedlicheKonstanten
Funktion mitWertebereichDaysmuss sieben F¨alle unterscheiden Beispiel:weekend:Days→Boolmit
weekend(d) =
True d=Sat∨d=Sun
False d=Mon∨d=Tue∨d=Wed∨ d=Thu∨d=Fri
Christoph L¨uth: Praktische Informatik 3 32 WS 08/09
Aufz¨ ahlung und Fallunterscheidung in Haskell
Definition
data Days = Mon | Tue | Wed | Thu | Fri | Sat | Sun Implizite Deklaration der KonstantenMon :: Days
Fallunterscheidung:
weekend :: Days -> Bool weekend d = case d of
Sat -> True Sun -> True Mon -> False Tue -> False Wed -> False Thu -> False Fri -> False
weekend d = case d of Sat -> True Sun -> True _ -> False
Christoph L¨uth: Praktische Informatik 3 33 WS 08/09
Fallunterscheidung in der Funktionsdefinition
Abk¨urzende Schreibweise (syntaktischer Zucker):
f c1=e1 . . . f cn=en
−→
f x=casexofc1->e1, . . . cn->en
Damit:
weekend :: Days -> Bool weekend Sat = True weekend Sun = True weekend _ = False
Christoph L¨uth: Praktische Informatik 3 34 WS 08/09
Der einfachste Aufz¨ ahlungstyp
EinfachsteAufz¨ahlung: Wahrheitswerte Bool={True,False}
Genau zwei unterschiedliche Werte Definitionvon Funktionen:
Wertetabellensind explizite Fallunterscheidungen
∧ True False True True False False False False
True ∧ True = True True ∧ False = False False ∧ True = False False ∧ False = False
Christoph L¨uth: Praktische Informatik 3 35 WS 08/09
Wahrheitswerte: Bool
Vordefiniertals
data Bool = True | False VordefinierteFunktionen:
not :: Bool-> Bool Negation
&& :: Bool-> Bool-> Bool Konjunktion
|| :: Bool-> Bool-> Bool Disjunktion Konjunktiondefiniert wie
a && b = case a of True -> b False -> False
&&,||sind rechtsnicht strikt False && div 1 0 == 0 False if then elseals syntaktischer Zucker:
ifbthenpelseq −→casebof True ->p False ->q
Christoph L¨uth: Praktische Informatik 3 36 WS 08/09
Beispiel: Ausschließende Disjunktion
Mathematische Definiton:
exOr :: Bool-> Bool-> Bool
exOr x y = (x || y) && (not (x && y)) Alternative 1:explizite Wertetabelle:
exOr False False = False exOr True False = True exOr False True = True exOr True True = False
Alternative 2:Fallunterscheidungauf ersten Argument exOr True y = not y
exOr False y = y Was ist ambesten?
Effizienz, Lesbarkeit, Striktheit
Christoph L¨uth: Praktische Informatik 3 37 WS 08/09
Produkte
Konstruktoren k¨onnenArgumentehaben Beispiel: EinDatumbesteht ausTag,Monat,Jahr Mathematisch: Produkt (Tupel)
Date = {Date (n, m, y)|n∈N,m∈Month,y∈N} Month = {Jan,Feb,Mar, . . .}
Funktionsdefinition:
Konstruktorargumente sindgebundene Variablen year(D(n,m,y)) = y
day(D(n,m,y)) = n
Bei derAuswertungwirdgebundene Variabledurchkonkretes Argument ersetzt
Produkte in Haskell
Konstruktoren mitArgumenten data Date = Date Int Month Int
data Month = Jan | Feb | Mar | Apr | May | Jun
| Jul | Aug | Sep | Oct | Nov | Dec Beispielwerte:
today = Date 5 Nov 2008 bloomsday = Date 16 Jun 1904
Uber¨ FallunterscheidungZugriff aufArgumenteder Konstruktoren:
day :: Date-> Int year :: Date-> Int
day d = case d of Date t m y-> t year (Date d m y) = y
Beispiel: Tag im Jahr
Tag im Jahr: Tag im laufenden Monat plus Summe der Anzahl der Tage der vorherigen Monate
yearDay :: Date-> Int
yearDay (Date d m y) = d + sumPrevMonths m where sumPrevMonths :: Month-> Int
sumPrevMonths Jan = 0
sumPrevMonths m = daysInMonth (prev m) y + sumPrevMonths (prev m) Tage im Monat ben¨otigt Jahr als Argument (Schaltjahr!) daysInMonth :: Month-> Int-> Int
prev :: Month-> Month Schaltjahr: Gregorianischer Kalender leapyear :: Int-> Bool
leapyear y = if mod y 100 == 0 then mod y 400 == 0 else mod y 4 == 0
Christoph L¨uth: Praktische Informatik 3 40 WS 08/09
Der Allgemeine Fall: Algebraische Datentypen
Definition einesalgebraischen DatentypenT:
data T= C1t1,1. . .t1,k1
. . .
| Cntn,1. . .tn,kn
KonstruktorenC1, . . . ,Cnsinddisjunkt:
Cix1. . .xn=Cjy1. . .ym=⇒i=j Konstruktorensindinjektiv:
C x1. . .xn=C y1. . .yn=⇒xi=yi Konstruktorenerzeugenden Datentyp:
∀x∈T.x=Ciy1. . .ym Diese Eigenschaften machenFallunterscheidungm¨oglich.
Christoph L¨uth: Praktische Informatik 3 41 WS 08/09
Rekursive Datentypen
Der definierte TypTkannrechtsbenutzt werden.
Entsprichtinduktiver Definition Rekursive Datentypen sindunendlich Beispielnat¨urliche Zahlen: Peano-Axiome
0∈N
wennn∈N, dannSn∈N Sinjektiv undSn6= 0
Induktionsprinzip — entspricht rekursiver Funktionsdefinition Induktionsprinziperlaubt Definitionrekursiver Funktionen:
n+ 0 = n n+S m = S(n+m)
Christoph L¨uth: Praktische Informatik 3 42 WS 08/09
Nat¨ urliche Zahlen in Haskell
Der Datentyp
data Nat = Zero | S Nat
Funktionen aufrekursivenTypen oftrekursivdefiniert:
add :: Nat-> Nat-> Nat add n Zero = n
add n (S m) = S (add n m)
Christoph L¨uth: Praktische Informatik 3 43 WS 08/09
Beispiel: Zeichenketten selbstgemacht
EineZeichenketteist entwederleer(das leere Wort)
oder einZeichenund eine weitereZeichenkette data MyString = Empty | Cons Char MyString Was istung¨unstigan dieser Repr¨asentation:
data MyString’ = Empty’
| Single Char
| Concat MyString’ MyString’
Christoph L¨uth: Praktische Informatik 3 44 WS 08/09
Funktionen auf Zeichenketten
L¨ange:
len :: MyString-> Int
len Empty = 0
len (Cons c str) = 1+ len str Verkettung:
cat :: MyString-> MyString-> MyString cat Empty t = t
cat (Cons c s) t = Cons c (cat s t) Umkehrung:
rev :: MyString-> MyString rev Empty = Empty
rev (Cons c t) = cat (rev t) (Cons c Empty)
Christoph L¨uth: Praktische Informatik 3 45 WS 08/09
Rekursive Typen in anderen Sprachen
Standard ML: gleich
Lisp: keine Typen, aber alles ist eine S-Expression data SExpr = Quote Atom | Cons SExpr SExpr Java: keine Entsprechung
Nachbildung durch Klassen, z.B. f¨ur Listen:
class List {
public List(Object theElement, ListNode n) { element = theElement;
next = n; } public Object element;
public List next; }
C: Produkte, Aufz¨ahlungen, keine rekursiven Typen
Christoph L¨uth: Praktische Informatik 3 46 WS 08/09
Das Rechnen mit Zahlen
Beschr¨ankteGenauigkeit,
konstanterAufwand ←→ beliebigeGenauigkeit, wachsenderAufwand Haskell bietet die Auswahl:
Int- ganze Zahlen als Maschinenworte (≥31 Bit) Integer- beliebig große ganze Zahlen
Rational- beliebig genaue rationale Zahlen Float- Fließkommazahlen (reelle Zahlen)
Christoph L¨uth: Praktische Informatik 3 47 WS 08/09
Ganze Zahlen: Int und Integer
N¨utzliche Funktionen (¨uberladen, auch f¨urInteger):
+, *, ^, - :: Int-> Int-> Int abs :: Int-> Int -- Betrag div, quot :: Int-> Int-> Int mod, rem :: Int-> Int-> Int Es gilt(div x y)*y + mod x y == x Vergleich durch==,/=,<=,<, . . . Achtung:Un¨ares Minus
Unterschied zum Infix-Operator- Im Zweifelsfall klammern:abs (-34)
Christoph L¨uth: Praktische Informatik 3 48 WS 08/09
Fließkommazahlen: Double
Doppeltgenaue Fließkommazahlen (IEEE 754 und 854)
Logarithmen, Wurzel, Exponentation,πunde, trigonometrische Funktionen Konversion in ganze Zahlen:
fromIntegral :: Int, Integer-> Double fromInteger :: Integer-> Double round, truncate :: Double-> Int, Integer Uberladungen mit Typannotation aufl¨¨ osen:
round (fromInt 10) :: Int Rundungsfehler!
Christoph L¨uth: Praktische Informatik 3 49 WS 08/09
Alphanumerische Basisdatentypen: Char
Notation f¨ur einzelneZeichen:’a’,. . . N¨utzlicheFunktionen:
ord :: Char -> Int chr :: Int -> Char toLower :: Char-> Char toUpper :: Char-> Char isDigit :: Char-> Bool isAlpha :: Char-> Bool
Zeichenketten:Listenvon Zeichen n¨achste Vorlesung
Christoph L¨uth: Praktische Informatik 3 50 WS 08/09
Zusammenfassung
Funktionsdefinitionen:
Abseitsregel, bedingteDefinition LokaleDefinitionen
Datentypen und Funktionsdefinitiondual Aufz¨ahlungen—Fallunterscheidung Produkte
RekursiveTypen — rekursive Funktionen WahrheitswerteBool
Numerische Basisdatentypen:
Int,Integer,RationalundDouble Alphanumerische Basisdatentypen:Char N¨achste Vorlesung: Abstraktion ¨uber Typen
Christoph L¨uth: Praktische Informatik 3 51 WS 08/09
Vorlesung vom 12.11.2008:
Typvariablen und Polymorphie
Christoph L¨uth: Praktische Informatik 3 52 WS 08/09
Fahrplan
Teil I: Grundlagen
Rekursion als Berechnungsmodell Rekursive Datentypen, rekursive Funktionen Typvariablen und Polymorphie
Funktionen h¨oherer Ordnung
Funktionaler Entwurf, Standarddatentypen Teil II: Abstraktion
Teil III: Beispiele, Anwendungen, Ausblicke
Christoph L¨uth: Praktische Informatik 3 53 WS 08/09
Inhalt
Letzte Vorlesung: rekursive Datentypen
Diese Vorlesung:
Abstraktion¨uber Typen:TypvariablenundPolymorphie Typinferenz: Wiebestimmeich denTypeinesAusdrucks?
Letzte Vorlesung: Zeichenketten
EineZeichenketteist entwederleer(das leere Wort)
oder einZeichenund eine weitereZeichenkette
data MyString = Empty
| Cons Char MyString
Funktionen auf Zeichenketten
L¨ange:
len :: MyString-> Int
len Empty = 0
len (Cons c str) = 1+ len str Verkettung:
cat :: MyString-> MyString-> MyString cat Empty t = t
cat (Cons c s) t = Cons c (cat s t) Umkehrung:
rev :: MyString-> MyString rev Empty = Empty
rev (Cons c t) = cat (rev t) (Cons c Empty)
Christoph L¨uth: Praktische Informatik 3 56 WS 08/09
Weiteres Beispiel: Liste von Zahlen
EineListe von Zahlenist entwederleer(das leere Wort) oder eineZahlund eine weitereListe
data IntList = Empty
| Cons Int IntList
Christoph L¨uth: Praktische Informatik 3 57 WS 08/09
Funktionen auf Zahlenlisten
L¨ange:
len :: IntList-> Int
len Empty = 0
len (Cons c str) = 1+ len str Verkettung:
cat :: IntList-> IntList-> IntList cat Empty t = t
cat (Cons c s) t = Cons c (cat s t) Umkehrung:
rev :: IntList-> IntList rev Empty = Empty
rev (Cons c t) = cat (rev t) (Cons c Empty)
Christoph L¨uth: Praktische Informatik 3 58 WS 08/09
Typvariablen
Typvariablenabstrahieren ¨uber Typen data List a = Empty
| Cons a (List a) aist eineTypvariable
akann mitCharoderIntinstantiiertwerden List aist einpolymorpherDatentyp Typvariableawird bei Anwendung instantiiert Signaturder Konstruktoren
Empty :: List a
Cons :: a-> List a-> List a
Christoph L¨uth: Praktische Informatik 3 59 WS 08/09
Polymorphe Datentypen
TypkorrekteTerme: Typ
Empty List a
Cons 57 Empty List Int
Cons 7 (Cons 8 Empty) List Int
Cons ’p’ (Cons ’i’ (Cons ’3’ Empty)) List Char
Cons True Empty List Bool
Nichttyp-korrekt:
Cons ’a’ (Cons 0 Empty) Cons True (Cons ’x’ Empty) wegenSignaturdes Konstruktors:
Cons :: a-> List a-> List a
Christoph L¨uth: Praktische Informatik 3 60 WS 08/09
Polymorphe Funktionen
Verkettung vonMyString:
cat :: MyString-> MyString-> MyString cat Empty t = t
cat (Cons c s) t = Cons c (cat s t) Verkettung vonIntList:
cat :: IntList-> IntList-> IntList cat Empty t = t
cat (Cons c s) t = Cons c (cat s t) GleicheDefinition,unterschiedlicherTyp
Zwei Instanzeneinerallgemeineren Definition.
Christoph L¨uth: Praktische Informatik 3 61 WS 08/09
Polymorphe Funktionen
Polymorphie erlaubtParametrisierung ¨uber Typen:
cat :: List a -> List a -> List a cat Empty ys = ys
cat (Cons x xs) ys = Cons x (cat xs ys) Typvariableawird bei Anwendung instantiiert:
cat (Cons 3 Empty) (Cons 5 (Cons 57 Empty)) cat (Cons ’p’ (Cons ’i’ Empty)) (Cons ’3’ Empty) abernicht
cat (Cons True Empty) (Cons ’a’ (Cons 0 Empty)) Typvariable: vergleichbar mit Funktionsparameter
Christoph L¨uth: Praktische Informatik 3 62 WS 08/09
Tupel
Mehr alseineTypvariable:
data Pair a b = Pair a b Konstruktorname = Typname Beispielterme:
Pair 4 "f¨unf"
Pair (Cons True Empty) ’a’
Pair (3+ 4) (Cons ’a’ Empty)
Christoph L¨uth: Praktische Informatik 3 63 WS 08/09
Typinferenz
Bestimmung desTypendurchTypinferenz Formalismus:Typableitungender Form
A`x::t
A— Typumgebung (ZuordnungSymbolezuTypen) x— Term
t— Typ
Herleitung durch f¨unfBasisregeln Notation:ts
x
xintdurchsersetzt Lambda-Abstraktion:f=\x->Ef¨urf x=E
Christoph L¨uth: Praktische Informatik 3 64 WS 08/09
Typinferenzregeln
A,x::t`x::t Ax A,x::s`e::t A` \x->e::s->tAbs A`e::s->t A`e0::s
A`e e0::t App A`e::t,Typvariableαnicht frei inA
A`e::ts α
Spec A`f::s A`ci::s A`ei::t
A`casef ofci->ei::t Cases
Christoph L¨uth: Praktische Informatik 3 65 WS 08/09
Polymorphie in anderen Programmiersprachen: Java
Polymorphie inJava: Methode auf alle Subklassen anwendbar class List {
public List(Object theElement, List n) { element = theElement;
next = n; } public Object element;
public List next; } KeineTypvariablen:
String s = "abc";
List l = new List(s, null);
l.elementhat TypObject, nichtString String e = (String)l.element;
Neu ab Java 1.5:Generics— damit echte Polymorphie m¨oglich
Christoph L¨uth: Praktische Informatik 3 66 WS 08/09
Polymorphie in anderen Programmiersprachen: C
“Polymorphie” in C:void * struct list {
void *head;
struct list *tail;
} Gegeben:
int x = 7;
struct list s = { &x, NULL };
s.headhat Typvoid *:
int y;
y= *(int *)s.head;
Nicht m¨oglich:headdirekt als Skalar (e.g.int) C++:Templates
Christoph L¨uth: Praktische Informatik 3 67 WS 08/09
Vordefinierte Datentypen: Tupel und Listen
Eingebautersyntaktischer Zucker Tupelsind das kartesische Produkt data (a, b) = (a, b)
(a, b)=alle Kombinationenvon Werten ausaundb Auch n-Tupel:(a,b,c)etc.
Listen
data [a] = [] | a : [a]
WeitereAbk¨urzungen:[x]= x:[],[x,y] = x:y:[]etc.
Christoph L¨uth: Praktische Informatik 3 68 WS 08/09
Ubersicht: vordefinierte Funktionen auf Listen I ¨
++ [a]-> [a]-> [a] Verketten
!! [a]-> Int-> a n-tes Element selektieren concat [[a]]-> [a] “flachklopfen”
length [a]-> Int L¨ange
head,last [a]-> a Erster/letztes Element tail,init [a]-> [a] (Hinterer/vorderer) Rest replicate Int-> a-> [a] ErzeugenKopien take Int-> [a]-> [a] Nimmt erstennElemente drop Int-> [a]-> [a] Entfernt erstenElemente splitAt Int-> [a]-> ([a], [a]) Spaltet ann-ter Position reverse [a]-> [a] Dreht Liste um
zip [a]-> [b]-> [(a, b)] Paare zu Liste von Paaren unzip [(a, b)]-> ([a], [b]) Liste von Paaren zu Paaren and,or [Bool]-> Bool Konjunktion/Disjunktion sum [Int]-> Int(¨uberladen) Summe
product [Int]-> Int(¨uberladen) Produkt
Christoph L¨uth: Praktische Informatik 3 69 WS 08/09
Zeichenketten: String
Stringsind Listen von Zeichen:
type String = [Char]
Alle vordefiniertenFunktionen auf Listenverf¨ugbar.
Syntaktischer Zuckerzur Eingabe:
[’y’,’o’,’h’,’o’] == "yoho"
Beispiel:
count :: Char-> String-> Int count c [] = 0
count c (x:xs) = if (c== x) then 1+ count c xs else count c xs
Beispiel: Palindrome
Palindrom:vorw¨artsundr¨uckw¨artsgelesengleich (z.B. Otto, Reliefpfeiler)
Signatur:
palindrom :: String-> Bool Entwurf:
Rekursive Formulierung:
erster Buchstabe = letzer Buchstabe, und Rest auch Palindrom Termination:
Leeres Wort und monoliterales Wort sind Palindrome Hilfsfunktionen:
last: String-> Char,init: String-> String
Beispiel: Palindrome
Implementierung:
palindrom :: String-> Bool palindrom [] = True palindrom [x] = True
palindrom (x:xs) = (x == last xs)
&& palindrom (init xs) Kritik:
Unterschied zwischen Groß- und kleinschreibung
palindrom (x:xs) = (toLower x == toLower (last xs))
&& palindrom (init xs) Nichtbuchstaben sollten nicht ber¨ucksichtigt werden.
Christoph L¨uth: Praktische Informatik 3 72 WS 08/09
Zusammenfassung
TypvariablenundPolymorphie:Abstraktion¨uber Typen
Typinferenz (Hindley-Damas-Milner):Herleitungdes Typen eines Ausdrucks
Vordefinierte Typen: Listen[a]und Tupel(a,b) N¨achste Woche: Funktionen h¨oherer Ordnung
Christoph L¨uth: Praktische Informatik 3 73 WS 08/09
Vorlesung vom 19.11.2008:
Funktionen h¨ oherer Ordnung
Christoph L¨uth: Praktische Informatik 3 74 WS 08/09
Fahrplan
Teil I: Grundlagen
Rekursion als Berechnungsmodell Rekursive Datentypen, rekursive Funktionen Typvariablen und Polymorphie
Funktionen h¨oherer Ordnung
Funktionaler Entwurf, Standarddatentypen Teil II: Abstraktion
Teil III: Beispiele, Anwendungen, Ausblicke
Christoph L¨uth: Praktische Informatik 3 75 WS 08/09
Inhalt
Funktionenh¨oherer Ordnung Funktionen alsgleichberechtigte Objekte Funktionen alsArgumente
Spezielle Funktionen:map,filter,foldund Freunde Formen derRekursion:
EinfacheundallgemeineRekursion Typklassen
Christoph L¨uth: Praktische Informatik 3 76 WS 08/09
Funktionen als Werte
RekursiveDefinitionen, z.B. ¨uber Listen:
concat :: [[a]]-> [a]
concat [] = []
concat (x:xs) = x ++ concat xs Argumente k¨onnen auchFunktionensein.
Beispiel: Funktionzweimalanwenden twice :: (a-> a)-> (a-> a) twice f x = f (f x)
Auswertung wie vorher:twice (twice inc) 3 7
Christoph L¨uth: Praktische Informatik 3 77 WS 08/09
Funktionen H¨ oherer Ordnung
Funktionen sindgleichberechtigt: Werte wiealle anderen Grundprinzipder funktionalen Programmierung FunktionenalsArgumente.
Vorz¨uge:
Modellierungallgemeiner Berechungsmuster H¨ohereWiederverwendbarkeit
Gr¨oßereAbstraktion
Christoph L¨uth: Praktische Informatik 3 78 WS 08/09
Funktionen als Argumente: Funktionskomposition
Funktionskomposition
(.) :: (b-> c) -> (a-> b)-> a-> c (f . g) x = f (g x)
Vordefiniert Lies:fnachg
Funktionskompositionvorw¨arts:
(>.>) :: (a-> b)-> (b-> c)-> a-> c (f >.> g) x = g (f x)
Nichtvordefiniert!
Christoph L¨uth: Praktische Informatik 3 79 WS 08/09
Funktionen als Argumente: map
Funktionauf alle Elemente anwenden:map Signatur:
map :: (a-> b)-> [a]-> [b]
Definition
map f [] = []
map f (x:xs) = (f x):(map f xs) Beispiel:
lowercase :: String-> String lowercase str = map toLower str
Christoph L¨uth: Praktische Informatik 3 80 WS 08/09
Funktionen als Argumente: filter
Elementefiltern:filter Signatur:
filter :: (a-> Bool)-> [a]-> [a]
Definition
filter p [] = []
filter p (x:xs)
| p x = x:(filter p xs)
| otherwise = filter p xs Beispiel:
qsort :: [a]-> [a]
qsort [] = []
qsort (x:xs) = qsort (filter (\y-> y< x) xs) ++
filter (\y-> y == x) (x:xs) ++
qsort (filter (\y-> x< y) xs)
Christoph L¨uth: Praktische Informatik 3 81 WS 08/09
Beispiel: Primzahlen
Sieb des Erathostenes
F¨ur jedegefundene PrimzahlpalleVielfachenheraussieben Dazu:filternmit\n-> mod n p /= 0
sieve :: [Integer]-> [Integer]
sieve [] = []
sieve (p:ps) =
p: sieve (filter (\n-> mod n p /= 0) ps) Primzahlen im Intervall[1.. n]:
primes :: Integer-> [Integer]
primes n = sieve [2..n]
NB: Mit2anfangen!
Listengenerator[n.. m]
Christoph L¨uth: Praktische Informatik 3 82 WS 08/09
Partielle Applikation
Funktionskonstruktorrechtsassoziativ:
a -> b-> c≡a-> (b-> c) Inbesondere:
(a -> b)-> c6=a-> (b-> c) PartielleAnwendung von Funktionen:
F¨urf :: a-> b-> c,x :: aistf x :: b-> c Beispiele:
map toLower :: String-> String 3 == :: Int-> Bool
concat . map (replicate 2) :: String-> String
Christoph L¨uth: Praktische Informatik 3 83 WS 08/09
Die K¨ urzungsregel
BeiAnwendungder Funktion
f :: t1 -> t2 -> ... -> tn-> t aufkArgumentemitk≤n
e1 :: t1, e2 :: t2, ..., ek :: tk werden dieTypen der Argumentegek¨urzt:
f :: t/1 -> t/2 -> ... -> t/k -> tk+1 -> ...-> tn -> t f e1 ...ek :: tk+1 -> ...-> tn -> t Beweis: RegelApp(letzte VL)
Christoph L¨uth: Praktische Informatik 3 84 WS 08/09
Einfache Rekursion
Einfache Rekursion: gegeben durch eine Gleichungf¨ur dieleere Liste eine Gleichungf¨ur dienicht-leere Liste Beispiel:
sum :: [Int]-> Int sum [] = 0 sum (x:xs) = x+ sum xs
Weitere Beispiele:length,concat,(++), . . . Auswertung:
sum [4,7,3] 4 + 7 + 3 + 0 concat [A, B, C] A ++ B ++ C++ []
Christoph L¨uth: Praktische Informatik 3 85 WS 08/09
Einfache Rekursion
Allgemeines Muster:
f [] = A
f (x:xs) = x⊗f xs Parameterder Definition:
Startwert (f¨ur die leere Liste)A :: b Rekursionsfunktion⊗:: a -> b-> b Auswertung:
f[x1, ...,xn] =x1⊗x2⊗. . .⊗xn⊗A Terminiertimmer
Entspricht einfacherIteration(while-Schleife)
Einfach Rekursion durch foldr
EinfacheRekursion Basisfall: leere Liste
Rekursionsfall: Kombination aus Listenkopf und Rekursionswert Signatur
foldr :: (a-> b-> b)-> b-> [a]-> b Definition
foldr f e [] = e
foldr f e (x:xs) = f x (foldr f e xs)
Beispiele: foldr
Beispiel: Summieren von Listenelementen.
sum :: [Int]-> Int sum xs = foldr (+) 0 xs
Beispiel: Flachklopfen von Listen.
concat :: [[a]]-> [a]
concat xs = foldr (++) [] xs
Christoph L¨uth: Praktische Informatik 3 88 WS 08/09
Noch ein Beispiel: rev
Listenumdrehen:
rev :: [a]-> [a]
rev [] = []
rev (x:xs) = rev xs ++ [x]
Mitfold:
rev xs = foldr snoc [] xs snoc :: a-> [a]-> [a]
snoc x xs = xs ++ [x]
Unbefriedigend: doppelte Rekursion
Christoph L¨uth: Praktische Informatik 3 89 WS 08/09
Einfache Rekursion durch foldl
foldrfaltet vonrechts:
foldr⊗[x1, ...,xn]A=x1⊗(x2⊗(. . .(xn⊗A))) Warum nichtandersherum?
foldl⊗[x1, ...,xn]A= (((A⊗x1)⊗x2). . .)⊗xn Definition vonfoldl:
foldl :: (a -> b -> a) -> a -> [b] -> a foldl f a [] = a
foldl f a (x:xs) = foldl f (f a x) xs
Christoph L¨uth: Praktische Informatik 3 90 WS 08/09
foldr vs. foldl
f=foldr⊗Aentspricht
f [] = A
f (x:xs) = x⊗f xs Kann nicht-strikt inxssein
f=foldl⊗Aentspricht
f xs = g A xs
g a [] = a
g a (x:xs) = g (a⊗x) xs Endrekursiv(effizient), aber strikt inxs
Christoph L¨uth: Praktische Informatik 3 91 WS 08/09
Noch ein Beispiel: rev revisited
Listenumkehr ist faltenvon links:
rev’ xs = foldl cons [] xs cons :: [a]-> a-> [a]
cons xs x = x: xs
Nur nocheineRekursion
Christoph L¨uth: Praktische Informatik 3 92 WS 08/09
foldl = foldr
Def:(⊗,A) ist einMonoidwenn
A⊗x=x (Neutrales Element links) x⊗A=x (Neutrales Element rechts) (x⊗y)⊗z=x⊗(y⊗z) (Assoziativ¨at)
Satz: Wenn (⊗,A)Monoid, dann
foldl⊗Axs=foldr⊗Axs
Christoph L¨uth: Praktische Informatik 3 93 WS 08/09
Funktionen H¨ oherer Ordnung: Java
Java: keine direkte Syntax f¨ur Funktionen h¨oherer Ordnung Folgendes istnichtm¨oglich:
interface Collection {
Object fold(Object f(Object a, Collection c), Object a) }
Aber folgendes:
interface Foldable { Object f (Object a); } interface Collection {
Object fold(Foldable f, Object a); }
VergleicheIteratoraus Collections Framework (Java SE 6):
public interface Iterator<E>
boolean hasNext();
E next(); }
Christoph L¨uth: Praktische Informatik 3 94 WS 08/09
Funktionen H¨ oherer Ordnung: C
Implizitvorhanden:
struct listel { void *hd;
struct listel *tl;
};
typedef struct listel *list;
list filter(int f(void *x), list l);
KeinedirekteSyntax (e.g. namenlose Funktionen) Typsystem zu schwach (keine Polymorphie) Funktionen = Zeiger auf Funktionen Benutzung:signal(C-Standard 7.14.1)
#include <signal.h>
void (*signal(int sig, void (*func)(int)))(int);
Christoph L¨uth: Praktische Informatik 3 95 WS 08/09
Funktionen H¨ oherer Ordnung: C
Implementierung vonfilter:
list filter(int f(void *x), list l) { if (l == NULL) {
return NULL;
} else {
list r;
r= filter(f, l-> tl);
if (f(l-> hd)) { l->tl= r;
return l;
} else {
free(l);
return r;
} } }
Christoph L¨uth: Praktische Informatik 3 96 WS 08/09
Ubersicht: vordefinierte Funktionen auf Listen II ¨
map (a-> b)-> [a]-> [b] Auf alle anwenden filter (a-> Bool)-> [a]-> [a] Elemente filtern foldr (a -> b -> b)
-> b -> [a] -> b
Falten von rechts foldl (a -> b -> a)
-> a -> [b] -> a
Falten von links takeWhile (a -> Bool) -> [a] -> [a] L¨angster Prefix s.t.pgilt dropWhile (a -> Bool) -> [a] -> [a] Rest davon
any (a-> Bool)-> [a]-> Bool any p = or . map p all (a-> Bool)-> [a]-> Bool all p = and . map p elem Eq a=> a-> [a]-> Bool elem x = any (x ==) zipWith (a -> b -> c)
-> [a] -> [b] -> [c]
Verallgemeinerteszip
Christoph L¨uth: Praktische Informatik 3 97 WS 08/09
Typklassen
Allgemeiner Typf¨urelem:
elem :: a-> [a]-> Bool zuallgemeinwegenc ==
(==)kannnichtf¨uralleTypen definiert werden:
GleichheitaufFunktionennicht entscheidbar.
z.B.(==) :: (Int-> Int)-> (Int-> Int)-> Bool Extensionalevs.intensionaleGleichheit
Christoph L¨uth: Praktische Informatik 3 98 WS 08/09
Typklassen
L¨osung:Typklassen
elem :: Eq a=> a-> [a]-> Bool elem c = any (c ==)
F¨urakann jeder Typ eingesetzt werden, f¨ur den(==)definiert ist.
Typklassen erlauben systematischesUberladen¨ (ad-hoc Polymorphie) Polymorphie: auf allen Typen gleich definiert
ad-hoc Polymorphie: unterschiedliche Definition f¨ur jeden Typ m¨oglich
Christoph L¨uth: Praktische Informatik 3 99 WS 08/09
Standard-Typklassen
Eq af¨ur== :: a-> a-> Bool(Gleichheit) Ord af¨ur<= :: a-> a-> Bool(Ordnung)
Alle Basisdatentypen Listen, Tupel Nichtf¨ur Funktionen
Damit auch Typ f¨urqsortoben:
qsort :: Ord a=> [a]-> [a]
Show af¨urshow :: a-> String AlleBasisdatentypen
Listen,Tupel Nichtf¨urFunktionen
Read af¨urread :: String-> a SieheShow
Christoph L¨uth: Praktische Informatik 3 100 WS 08/09
Allgemeine Rekursion
EinfacheRekursion istSpezialfallderallgemeinen Rekursion AllgemeineRekursion:
Rekursion ¨ubermehrere Argumente Rekursion ¨uberandere Datenstruktur Andere Zerlegungals Kopf und Rest
Christoph L¨uth: Praktische Informatik 3 101 WS 08/09
Beispiele f¨ ur allgemeine Rekursion: Sortieren
Quicksort:
zerlege Liste in Elementekleiner,gleichundgr¨oßerdem ersten, sortiereTeilst¨ucke,konkateniereErgebnisse
Mergesort:
teileListe in derH¨alfte,
sortiereTeilst¨ucke, f¨ugeordnungserhaltendzusammen.
Beispiel f¨ ur allgemeine Rekursion: Mergesort
Hauptfunktion:
msort :: [Int]-> [Int]
msort xs
| length xs <= 1 = xs
| otherwise = merge (msort front) (msort back) where (front, back) = splitAt ((length xs) ‘div‘ 2) xs splitAt :: Int-> [a]-> ([a], [a])spaltetListe auf
Hilfsfunktion: ordnungserhaltendes Zusammenf¨ugen merge :: [Int]-> [Int]-> [Int]
merge [] x = x merge y [] = y merge (x:xs) (y:ys)
| x<= y = x:(merge xs (y:ys))
| otherwise = y:(merge (x:xs) ys)
Zusammenfassung
Funktionenh¨oherer Ordnung
Funktionen alsgleichberechtigte ObjekteundArgumente
Spezielle Funktionen h¨oherer Ordnung:map,filter,foldund Freunde Partielle Applikation, K¨urzungsregel
Formen derRekursion:
EinfacheundallgemeineRekursion EinfacheRekursion entsprichtfold Typklassen
Uberladen¨ von Bezeichnern
Christoph L¨uth: Praktische Informatik 3 104 WS 08/09
Vorlesung vom 26.11.08:
Funktionaler Entwurf &
Standarddatentypen
Christoph L¨uth: Praktische Informatik 3 105 WS 08/09
Fahrplan
Teil I: Grundlagen
Rekursion als Berechnungsmodell Rekursive Datentypen, rekursive Funktionen Typvariablen und Polymorphie
Funktionen h¨oherer Ordnung
Funktionaler Entwurf, Standarddatentypen Teil II: Abstraktion
Teil III: Beispiele, Anwendungen, Ausblicke
Christoph L¨uth: Praktische Informatik 3 106 WS 08/09
Inhalt
Funktionaler Entwurf und Entwicklung Spezifikation
Programmentwurf Implementierung Testen Beispiele
Standarddatentypen:Maybe, B¨aume
Christoph L¨uth: Praktische Informatik 3 107 WS 08/09
Funktionaler Entwurf und Entwicklung
1 Spezifikation:
Definitionsbereich(Eingabewerte) Wertebereich(Ausgabewerte) Anforderungendefinieren
Anforderungen alsEigenschaftenformulieren Signatur
2 Programmentwurf:
Wie kann das Problem inTeilprobleme zerlegtwerden?
Wie k¨onnenTeill¨osungen zusammengesetztwerden?
Gibt es ein ¨ahnliches (gel¨ostes) Problem?
Erster Entwurf
Christoph L¨uth: Praktische Informatik 3 108 WS 08/09
Funktionaler Entwurf und Entwicklung
3 Implementierung:
Effizienz
Wie w¨urde manKorrektheitheit zeigen?
Termination
Gibt es hilfreicheB¨uchereifunktionen
Refaktorierung: m¨ogliche Verallgemeinerungen,shared code Lauff¨ahige Implementierung
4 Test:
Black-box Test:Testdaten aus derSpezifikation White-box Test:Testdaten aus derImplementierung Testdaten: hoheAbdeckung,Randf¨allebeachten.
quickcheck: automatische Testdatenerzeugung
Christoph L¨uth: Praktische Informatik 3 109 WS 08/09
Der Programmentwicklungszyklus im kleinen
Lösung implementieren Test &
Evaluation
Lösung entwerfen (Spezfikation)
Problem verstehen
Christoph L¨uth: Praktische Informatik 3 110 WS 08/09
Vorgehensmodelle im Großen
Systemarchitektur
Implementierung Unit Tests Modulentwurf
Integrationstests Systeminte- grationstests
Systementwurf
Validationstests Anforderungs-
spezifikation
Validation
V-Modell
Christoph L¨uth: Praktische Informatik 3 111 WS 08/09
1. Beispiel: gr¨ oßter gemeinsame Teiler
Definitionsbereich:Int Int Wertebereich:Int Spezifikation:
Teiler:a|b ⇐⇒ ∃n.a·n=b
GemeinsamerTeiler: is cd(x,y,z)⇐⇒z|x∧z|y
Grenzen: gcd(x,y)≤x,gcd(x,y)≤ydamit gcd(x,y)≤min(x,y) gr¨oßtergemeinsamer Teiler:∀i.gcd(x,y)<i≤min(x,y) =⇒ ¬cd(x,y,i)
Christoph L¨uth: Praktische Informatik 3 112 WS 08/09
ggT: Spezifikation
Signatur
gcd :: Int-> Int-> Int
Eigenschaften(ausf¨uhrbare Spezifikationen) formulieren Problem:Existenzquantor— besser:a|b⇐⇒b moda= 0 divides :: Int-> Int-> Bool
divides a b = mod b a == 0 Gemeinsamer Teiler:
is_cd :: Int-> Int-> Int-> Bool is_cd x y a = divides a x && divides a y Gr¨oßter gemeinsamer Teiler:
no_larger :: Int-> Int-> Int-> Bool
no_larger x y g = all (\i-> not (is_cd x y i)) [g .. min x y]
Christoph L¨uth: Praktische Informatik 3 113 WS 08/09
ggT: Analyse
Reduktion auf kleineres Teilproblem:a|b⇐⇒ ∃n.a·n=b Fallunterscheidung:
n= 1 danna=b
n=m+ 1, danna(m+ 1) =am+a=b, alsoam=b−a⇐⇒a|b−a Damit Abbruchbedingung: beide Argumente gleich
Reduktion:a<b gcd(a,b) = gcd(a,b−a) Besser:a<b gcd(a,b) = gcd(b−a,a) Implementierung:
gcd a b
| a == b = a
| a < b = gcd (b- a) a
| otherwise = gcd b a
Christoph L¨uth: Praktische Informatik 3 114 WS 08/09
Kritik der L¨ osung
Terminiert nichtbeinegativenZahlen oder 0.
gcd2 :: Int-> Int-> Int
gcd2 a b = gcd’ (abs a) (abs b) where
gcd’ a b | a == 0 && b == 0 = error "gcd 0 0 undefined"
| a == b || b == 0 = a
| a < b = gcd’ (b- a) a
| otherwise = gcd’ b a
Ineffizient — es gilt auch gcd(a,b) = gcd(b,a modb) (Euklid’scher Algorithmus)
Es gibt eineB¨uchereifunktion.
Christoph L¨uth: Praktische Informatik 3 115 WS 08/09
2. Beispiel: das n-K¨ oniginnen-Problem
Problem:nK¨oniginnen aufn×n-Schachbrett sicher plazieren Spezifikation:
Position der K¨oniginnen type Pos = (Int, Int)
Eingabe: Anzahl K¨oniginnen,R¨uckgabe: Positionen queens :: Int-> [[Pos]]
Christoph L¨uth: Praktische Informatik 3 116 WS 08/09
n-K¨ oniginnen: Spezifikation
Sichergdw. kein gegenseitigesSchlagen.
Diagonalen:x−y=c,x+y=c0
(x,y)∼(p,q)⇐⇒ x6=p∧y6=q∧x−y6=p−q∧x+y6=p+q Spezifikation:
AlleL¨osungensind auf dem Feld, alleL¨osungenhabennPositionen, und sind gegenseitigsicher:
∀Q∈queens(n).∀(x,y)∈Q.1≤x≤n∧1≤y≤n
∀Q∈queens(n).|Q|=n
∀Q∈queens(n).∀p1,p2∈Q.p1=p2∨p1∼p2
Christoph L¨uth: Praktische Informatik 3 117 WS 08/09
n-K¨ oniginnen: Eigenschaften
Eigenschaften(ausf¨uhrbareSpezifikation):
inRange :: Int-> Pos-> Bool
inRange n (x, y) = 1 <= x && x <= n && 1 <= y && y <= n enough :: Int-> [Pos]-> Bool
enough n q = length q == n isSafe :: Pos-> Pos-> Bool isSafe (x, y) (p, q) =
x /= p && y /= q && x- y /= p- q && x+ y /= p+ q allSafe :: [Pos]-> Bool
allSafe q =
all (\p-> all (\r-> (p == r || isSafe p r)) q) q isSolution :: Int-> [[Pos]]-> Bool
isSolution n q = all (all (inRange n)) q && all (enough n) q && all allSafe q Schon fast eine L¨osung, aberkombinatorische Explosion
Christoph L¨uth: Praktische Informatik 3 118 WS 08/09
n-K¨ oniginnen: Rekursive Formulierung
Rekursive Formulierung:
Keine K¨onigin— kein Problem.
L¨osung f¨urnK¨oniginnen: L¨osung f¨urn−1 K¨oniginnen, n-te K¨onigin so stellen, dass siekeine andere bedroht.
Vereinfachung:n-te K¨oniginmuß inn-ter Spalteplaziert werden.
Limitiertkombinatorische Explosion
Christoph L¨uth: Praktische Informatik 3 119 WS 08/09
n-K¨ oniginnen: Hauptfunktion
Hauptfunktion:
Seipneue Zeile
cand pbisherige Teill¨osungen, die mit(n, p)sicher sind put p qf¨ugt neue Positionpzu Teill¨osungqhinzu queens num = putqueens num where
putqueens :: Int-> [[Pos]]
putqueens n = if n == 0 then [[]]
else let cand p = filter (\q-> safe q (n, p)) (putqueens (n-1)) put p q = q ++ [(n, p)]
in concatMap (\p-> map (put p) (cand p)) [1.. num]
Rekursion¨uber Anzahl der K¨oniginnen DaherTermination
Christoph L¨uth: Praktische Informatik 3 120 WS 08/09
Das n-K¨ oniginnen-Problem
Sichere neuePosition: durchkeine andere bedroht safe :: [Pos]-> Pos-> Bool
safe others p = all (not . threatens p) others Gegenseitige Bedrohung:
Bedrohungwenn ingleicher Zeile, Spalte, oder Diagonale.
threatens :: Pos-> Pos-> Bool threatens (i, j) (m, n) =
(j== n) || (i+j == m+n) || (i-j == m-n) Test auf gleicher Spaltei==munn¨otig.
Christoph L¨uth: Praktische Informatik 3 121 WS 08/09
Das n-K¨ oniginnen-Problem: Testen
Testdaten (manuell):
queens 0,queens 1,queens 2,queens 3,queens 4
Test (automatisiert):
all (\n-> is\_solution n (queens n)) [1.. 8]
Christoph L¨uth: Praktische Informatik 3 122 WS 08/09
3. Beispiel: Der Index
Problem:
Gegeben einText
br¨osel fasel\nbr¨osel br¨osel\nfasel br¨osel blubb
Zu erstellen einIndex: f¨urjedes WortListe derZeilen, in der esauftritt br¨osel [1, 2, 3] blubb [3] fasel [1, 3]
Spezifikationder L¨osung type Doc = String type Word= String
makeIndex :: Doc-> [([Int], Word)]
KeineLeereintr¨age
Alle W¨orter imIndexm¨ussen imTextin derangegebenen Zeileauftreten
Christoph L¨uth: Praktische Informatik 3 123 WS 08/09
Der Index: Eigenschaften
KeineLeereintr¨age
notEmpty :: [([Int], Word)] -> Bool
notEmpty idx = all (\ (l, w)-> not (null l)) idx Alle W¨orter imIndexim Text in derangegebenen Zeile
NB. Index erster Zeile ist 1.
occursInLine :: Word-> Int-> Doc-> Bool
occursInLine w l txt = isInfixOf w (lines txt !! (l-1)) Eigenschaften, zusammengefasst:
prop_notempty :: String-> Bool
prop_notempty doc = notEmpty (makeIndex doc) prop_occurs :: String-> Bool
prop_occurs doc =
all (\ (ls, w)-> all (\l-> occursInLine w l doc) ls) (makeIndex doc)
Christoph L¨uth: Praktische Informatik 3 124 WS 08/09
Zerlegung des Problems: erste N¨ aherung
Text inZeilenzerteilen Zeilen inW¨orterzerteilen
Jedes Wort mitZeilennummerversehen Gleiche Wortezusammenfassen Sortieren
Christoph L¨uth: Praktische Informatik 3 125 WS 08/09
Zerlegung des Problems: zweite N¨ aherung
Ergebnistyp
1 Text inZeilen aufspalten: [Line]
(mittype Line= String)
2 JedeZeilemit ihrerNummerversehen: [(Int, Line)]
3 ZeileninW¨orterspalten (Zeilennummer beibehalten):
[(Int, Word)]
4 Listealphabetischnach W¨orternsortieren: [(Int, Word)]
5 Gleiche W¨orterin unerschiedlichen Zeilenzusammenfassen:
[([Int], Word)]
6 AlleW¨orter mit weniger als vier Buchstabenentfernen:
[([Int], Word)]
Christoph L¨uth: Praktische Informatik 3 126 WS 08/09
Erste Implementierung:
type Line = String makeIndex =
shorten . -- -> [([Int], Word)]
amalgamate . -- -> [([Int],Word)]
makeLists . -- -> [([Int],Word)]
sortLs . -- -> [(Int,Word)]
allNumWords . -- -> [(Int,Word)]
numLines . -- -> [(Int, Line)]
lines -- Doc-> [Line]
Christoph L¨uth: Praktische Informatik 3 127 WS 08/09
Implementierung von Schritt 1–2
InZeilen zerlegen:lines :: String-> [String]
JedeZeilemit ihrerNummerversehen:
numLines :: [Line]-> [(Int, Line)]
numLines lines = zip [1.. length lines] lines JedeZeileinW¨orterzerlegen:
Pro Zeilewords:: String-> [String]
Ber¨ucksichtigt nurLeerzeichen.
Vorher alleSatzzeichendurchLeerzeichen ersetzen.
Christoph L¨uth: Praktische Informatik 3 128 WS 08/09
Implementierung von Schritt 3
Zusammengenommen:
splitWords :: Line-> [Word]
splitWords = words . map (\c-> if isPunct c then ’ ’ else c) where isPunct :: Char-> Bool
isPunct c = c ‘elem‘ ";:.,\’\"!?(){}-\\[]"
Aufalle Zeilenanwenden, Ergebnislisteflachklopfen.
allNumWords :: [(Int, Line)]-> [(Int, Word)]
allNumWords = concatMap oneLine where oneLine :: (Int, Line)-> [(Int, Word)]
oneLine (num, line) = map (\w-> (num, w)) (splitWords line)
Christoph L¨uth: Praktische Informatik 3 129 WS 08/09
Einschub: Ordnungen
Generische Sortierfunktion Ordnung alsParameter
qsortBy :: (a-> a-> Bool)-> [a]-> [a]
qsortBy ord [] = []
qsortBy ord (x:xs) =
qsortBy ord (filter (\y-> ord y x) xs) ++ [x] ++
qsortBy ord (filter (\y-> not (ord y x)) xs) Vordefiniert (aber andereSignatur):
sortBy ::(a-> a-> Ordering)-> [a]-> [a]
Christoph L¨uth: Praktische Informatik 3 130 WS 08/09
Implementation von Schritt 4
Listealphabetischnach W¨orternsortieren:
Ordnungsrelationdefinieren:
ordWord :: (Int, Word)-> (Int, Word)-> Bool ordWord (n1, w1) (n2, w2) =
w1 < w2 || (w1 == w2 && n1 <= n2) Sortieren mit generischer SortierfunktionqsortBy sortLs :: [(Int, Word)]-> [(Int, Word)]
sortLs = qsortBy ordWord
Christoph L¨uth: Praktische Informatik 3 131 WS 08/09
Implementation von Schritt 5
Gleiche W¨orterinunterschiedlichen Zeilenzusammenfassen:
Erster Schritt: JedeZeilezu (einelementiger)Liste von Zeilen.
makeLists :: [(Int, Word)]-> [([Int], Word)]
makeLists = map (\ (l, w)-> ([l], w)) Zweiter Schritt:Gleiche W¨orterzusammenfassen.
Nach Sortierung sindgleiche W¨orter hintereinander!
amalgamate :: [([Int], Word)]-> [([Int],Word)]
amalgamate [] = []
amalgamate [p] = [p]
amalgamate ((l1, w1):(l2, w2):rest)
| w1 == w2 = amalgamate ((l1++ l2, w1):rest)
| otherwise = (l1, w1):amalgamate ((l2, w2):rest)
Christoph L¨uth: Praktische Informatik 3 132 WS 08/09
Implementation von Schritt 6 — Test
AlleW¨ortermitweniger als vier Buchstabenentfernen:
shorten :: [([Int],Word)] -> [([Int],Word)]
shorten = filter (\ (_, wd)-> length wd >= 4) AlternativeDefinition:
shorten = filter ((>= 4) . length . snd) Testf¨alle:
makeIndex ""
makeIndex "a b a"
makeIndex "abcdef abcde"
makeIndex "a eins zwei\nzwei\nzwei,eins"
Christoph L¨uth: Praktische Informatik 3 133 WS 08/09
Standarddatentypen
Listen[a]
Paare(a,b)
LiftingMaybe a
B¨aume
Modellierung von Fehlern: Maybe a
TypaplusFehlerelement Im Prelude vordefiniert.
data Maybe a = Just a | Nothing NothingmodelliertFehlerfall:
find :: (a-> Bool)-> [a]-> Maybe a find p [] = Nothing
find p (x:xs) = if p x then Just x else find p xs
Funktionen auf Maybe a
Anwendung von Funktion mit Default-Wert f¨ur Fehler (vordefiniert):
maybe :: b -> (a -> b) -> Maybe a -> b maybe d f Nothing = d
maybe d f (Just x) = f x
Liftenvon Funktionen ohne Fehlerbehandlung:
Fehler bleibenerhalten.
fmap :: (a-> b)-> Maybe a-> Maybe b fmap f Nothing = Nothing
fmap f (Just x)= Just (f x)
Christoph L¨uth: Praktische Informatik 3 136 WS 08/09
Bin¨ are B¨ aume
Ein bin¨arer Baum ist Entweder leer,
oder ein Knoten mit genauzweiUnterb¨aumen.
Knoten tragen eine Markierung.
data Tree a = Null
| Node (Tree a) a (Tree a)
AndereM¨oglichkeit:UnterschiedlicheMarkierungen Bl¨atter und Knoten data Tree’ a b = Null’
| Leaf’ b
| Node’ (Tree’ a b) a (Tree’ a b)
Christoph L¨uth: Praktische Informatik 3 137 WS 08/09
Funktionen auf B¨ aumen
Test aufEnthaltensein:
member :: Eq a=> Tree a-> a-> Bool member Null _ = False
member (Node l a r) b =
a == b || (member l b) || (member r b) H¨ohe:
height :: Tree a-> Int height Null = 0
height (Node l a r) = max (height l) (height r) + 1
Christoph L¨uth: Praktische Informatik 3 138 WS 08/09
Funktionen auf B¨ aumen
Primitive Rekursionauf B¨aumen:
Rekursionsanfang Rekursionsschritt:
Label des Knotens,
ZweiR¨uckgabewerte f¨urlinkenundrechtenUnterbaum.
foldT :: (a-> b-> b-> b)-> b-> Tree a-> b foldT f e Null = e
foldT f e (Node l a r) = f a (foldT f e l) (foldT f e r)
Christoph L¨uth: Praktische Informatik 3 139 WS 08/09
Funktionen auf B¨ aumen
DamitElementtest:
member’ :: Eq a=> Tree a-> a-> Bool member’ t x =
foldT (\e b1 b2-> e == x || b1 || b2) False t H¨ohe:
height’ :: Tree a-> Int
height’ = foldT (\ _ h1 h2-> 1+ max h1 h2) 0
Christoph L¨uth: Praktische Informatik 3 140 WS 08/09
Funktionen auf B¨ aumen
Traversion:preorder,inorder,postorder preorder :: Tree a-> [a]
inorder :: Tree a-> [a]
postorder :: Tree a-> [a]
preorder = foldT (\x t1 t2-> [x]++ t1++ t2) []
inorder = foldT (\x t1 t2-> t1++ [x]++ t2) []
postorder = foldT (\x t1 t2-> t1++ t2++ [x]) []
Aquivalente Definition ohne¨ foldT:
preorder’ Null = []
preorder’ (Node l a r) = [a] ++preorder’ l ++preorder’ r Wie w¨urde mangeordnete B¨aumeimplementieren?
Christoph L¨uth: Praktische Informatik 3 141 WS 08/09
Zusammenfassung
FunktionalerEntwurf:
Entwurf:Signatur,Eigenschaften
Implementierung:Zerlegung,Reduktion,Komposition Testen: Testdaten,quickcheck
Ggf. wiederholen
Standarddatentypen:Maybe a,B¨aume N¨achste Woche:abstrakteDatentypen
Christoph L¨uth: Praktische Informatik 3 142 WS 08/09 Christoph L¨uth: Praktische Informatik 3 143 WS 08/09
y
Vorlesung vom 10.12.08:
Signaturen und Eigenschaften
Christoph L¨uth: Praktische Informatik 3 143 WS 08/09
Fahrplan
Teil I: Grundlagen Teil II: Abstraktion
Abstrakte Datentypen Signaturen & Axiome Korrektheit von Programmen Zustand und Aktionen
Teil III: Beispiele, Anwendungen, Ausblicke
Christoph L¨uth: Praktische Informatik 3 144 WS 08/09
Abstrakte Datentypen
Letzte Vorlesung:Abstrakte Datentypen
TypplusOperationen In Haskell:Module
Heute:SignaturenundEigenschaften
Christoph L¨uth: Praktische Informatik 3 145 WS 08/09
Signaturen
Definition:DieSignatureines abstrakten Datentyps besteht aus den Typen, und der Signatur der Funktionen darauf.
Obs: Keine direkte Repr¨asentation in Haskell
Signatur: Typ eines Moduls
Christoph L¨uth: Praktische Informatik 3 146 WS 08/09
Der Speicher: Signatur
EinSpeicher(Store, FiniteMap, State)
Typen: der eigentliche SpeicherS, Adressena, Werteb Operationen:
leererSpeicher:S
in Speicher an eine Stelle einen Wertschreiben:S→a→b→S aus Speicher an einer Stelle einen Wertlesen:S→a*b(partiell)
Christoph L¨uth: Praktische Informatik 3 147 WS 08/09
Der Speicher: Signatur
AdressenundWertesindParameter type Store a b
Leerer Speicher:
empty :: Store a b
In Speicher an eine Stelle einen Wertschreiben:
upd :: Store a b-> a -> b-> Store a b Aus Speicher an einer Stelle einen Wertlesen:
get :: Store a b-> a -> Maybe b
Christoph L¨uth: Praktische Informatik 3 148 WS 08/09
Signatur und Eigenschaften
Signatur genug, um ADTtypkorrektzu benutzen
InsbesondereAnwendbarkeitundReihenfolge
Signatur nicht genug, umBedeutung(Semantik) zu beschreiben
Beispiel Speicher: Was wirdgelesen? Wieverh¨altsich der Speicher?
Beschreibung von Eigenschaften: Axiome
AxiomesindPr¨adikate¨uber denOperationender Signatur ElementarePr¨adikateP
Gleichheits==t
BedingtePr¨adikate:A=⇒B
BeobachtbareTypen: interne Struktur bekannt
Vordefinierte Typen (Zahlen,Zeichen,Listen), algebraische Datentypen AbstrakteTypen: interne Struktur unbekannt
Gleichheit (wenn definiert)