• Keine Ergebnisse gefunden

Vorlesung vom 29.10.2008: Einf¨uhrung

N/A
N/A
Protected

Academic year: 2022

Aktie "Vorlesung vom 29.10.2008: Einf¨uhrung"

Copied!
33
0
0

Wird geladen.... (Jetzt Volltext ansehen)

Volltext

(1)

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

(2)

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

(3)

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)

(4)

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

(5)

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

(6)

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

(7)

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

(8)

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

(9)

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

(10)

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

(11)

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)

(12)

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

(13)

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)

(14)

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

(15)

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

(16)

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

(17)

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

(18)

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

(19)

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)

Referenzen

ÄHNLICHE DOKUMENTE

Beweis: Simulationstechnik Durch Induktion ¨uber Aufbau der µ- rekursiven Ausdr¨ucken zeige, dass jede partiell rekursive Funktion durch ein while-Programm berechenbar ist.. Somit

Weil das erste Paar schon im ersten Monat Nachwuchs bekommt, kann man es verdoppeln, so dass nach einem Monat 2 Paare da sind.. Von diesen vermehrt sich das erste im zweiten

Wir konstruieren eine 3-Band-Turing-Maschine M 0 , die schrittweise die Arbeit von M simuliert:.. Auf dem ersten Arbeitsband speichern wir im Wesentlichen die Konfiguration der

Praktische Informatik 3: Funktionale Programmierung Vorlesung 3 vom 28.10.2014: Rekursive Datentypen.. Christoph Lüth Universität Bremen

Praktische Informatik 3: Funktionale Programmierung Vorlesung 3 vom 30.10.2012: Rekursive Datentypen.. Christoph Lüth Universität Bremen

Cons ’p’ (Cons ’i’ (Cons ’3’ Empty)) List Char. Cons True Empty

der Compiler kennt nur, was er bereits gelesen hat, aber keine anderen Dateien → globale Variablen und alle Funktionen gelten vom Deklarationspunkt bis zum Ende der Datei

Die Funktion getchar() hat das erste Zeichen dem Tastaturpuffer Die Funktion getchar() hat das erste Zeichen dem Tastaturpuffer entnommen.. Es ist der Variablen x