Praktische Informatik 3: Funktionale Programmierung Vorlesung 2 vom 25.10.2016: Funktionen und Datentypen
Christoph Lüth Universität Bremen Wintersemester 2016/17
16:02:20 2017-01-17 1 [38]
Fahrplan
I Teil I: Funktionale Programmierung im Kleinen
IEinführung
I Funktionen und Datentypen
IAlgebraische Datentypen
ITypvariablen und Polymorphie
IFunktionen höherer Ordnung I
IFunktionen höherer Ordnung II und Effizenzaspekte I Teil II: Funktionale Programmierung im Großen I Teil III: Funktionale Programmierung im richtigen Leben
PI3 WS 16/17 2 [38]
Inhalt
I Organisatorisches I Definition vonFunktionen
I SyntaktischeFeinheiten
I Bedeutung von Haskell-Programmen
I Striktheit
I Definition vonDatentypen
I Aufzählungen
I Produkte
PI3 WS 16/17 3 [38]
Organisatorisches
I Verteilung der Tutorien (laut stud.ip):
Mi 08 – 10 GW1 A0160 Berthold Hoffmann 16 (50) 4 10 – 12 GW1 A0160 Johannes Ganser 43 (50) 9 12 – 14 MZH 1110 Johannes Ganser 35 (35) 9 14 – 16 GW1 B2070 Alexander Kurth 25 (25) 7 Do 08 – 10 MZH 1110 Tobias Brandt 33 (35) 10
10 – 12 GW1 B2130 Tristan Bruns 25 (25) 11 I Insgesamt 50 Gruppen (ca. 8 pro Tutorium)
I Wenn möglich, frühes Mittwochstutorium belegen.
PI3 WS 16/17 4 [38]
Definition von Funktionen
PI3 WS 16/17 5 [38]
Definition von Funktionen
I Zwei wesentlicheKonstrukte:
IFallunterscheidung
IRekursion Satz
Fallunterscheidung und Rekursion auf natürlichen Zahlen sind Turing-mächtig.
I Funktionen müssenpartiellsein können.
PI3 WS 16/17 6 [38]
Haskell-Syntax: Charakteristika
I Leichtgewichtig
I Wichtigstes Zeichen:
I Funktionsapplikation:f a
I KeineKlammern
I HöchstePriorität (engste Bindung)
I Abseitsregel: Gültigkeitsbereich durch Einrückung
I KeineKlammern({. . .})
I Auch in anderenSprachen(Python, Ruby)
PI3 WS 16/17 7 [38]
Haskell-Syntax: Funktionsdefinition
Generelle Form:
I Signatur:
max :: Int→ Int→ Int
I Definition:
max x y = i f x<y theny else x
IKopf, mit Parametern
IRumpf(evtl. länger, mehrere Zeilen)
ITypischesMuster: Fallunterscheidung, dann rekursiver Aufruf
IWas gehört zum Rumpf (Geltungsberereich)?
PI3 WS 16/17 8 [38]
Haskell-Syntax I: Die Abseitsregel
Funktionsdefinition:
f x1x2. . .xn=E I Geltungsbereichder Definition vonf:
alles, was gegenüberfeingerücktist.
I Beispiel:
f x = h i e r faengts an und h i e r gehts weiter
immer weiter
g y z = und h i e r faengt was neues an I Gilt auchverschachtelt.
I Kommentare sindpassiv(heben das Abseits nicht auf).
PI3 WS 16/17 9 [38]
Haskell-Syntax II: Kommentare
I Pro Zeile: Ab−−bis Ende der Zeile
f x y = irgendwas −−und hier der Kommentar!
I Über mehrere Zeilen: Anfang{−, Ende−}
{−
Hier faengt der Kommentar an e r s tr e c k t sich ueber mehrere Zeilen
b i s h i e r −}
f x y = irgendwas
IKann geschachtelt werden.
PI3 WS 16/17 10 [38]
Haskell-Syntax III: Bedingte Definitionen
I Statt verschachtelter Fallunterscheidungen . . . f x y =i f B1thenP else
i f B2thenQelse. . . . . .bedingte Gleichungen:
f x y
| B1 =. . .
| B2 =. . .
I Auswertung der Bedingungen von oben nach unten I Wenn keine Bedingung wahr ist:Laufzeitfehler! Deshalb:
| otherwise =. . .
PI3 WS 16/17 11 [38]
Haskell-Syntax IV: Lokale Definitionen
I Lokale Definitionen mitwhereoderlet:
f x y
| g = P y
| otherwise = f x where y = M
f x = N x
f x y = let y = M
f x = N x in i f g thenP y
else f x I f,y, . . . werdengleichzeitigdefiniert (Rekursion!) I Namenf,yund Parameter (x)überlagernandere I Es gilt dieAbseitsregel
IDeshalb:Aufgleiche Einrückungder lokalen Definition achten!
PI3 WS 16/17 12 [38]
Bedeutung von Funktionen
PI3 WS 16/17 13 [38]
Bedeutung (Semantik) von Programmen
I OperationaleSemantik:
IDurch denAusführungsbegriff
IEin Programm ist, was es tut.
I DenotationelleSemantik:
IProgramme werden aufmathematische Objekteabgebildet (Denotat).
IFür funktionale Programme:rekursivdefinierte Funktionen Äquivalenz von operationaler und denotationaler Semantik
SeiPein funktionales Programm,→P die dadurch definierte Reduktion, und [[P]] das Denotat. Dann gilt für alle Ausdrücketund Wertev
t→Pv ⇐⇒ [[P]](t) =v
PI3 WS 16/17 14 [38]
Auswertungsstrategien
inc :: Int → Int inc x = x+ 1
double :: Int → Int double x = 2∗x I Reduktion voninc ( double ( inc 3))
I Vonaußennachinnen(outermost-first):
inc ( double ( inc 3)) →double (inc 3)+ 1
→2*(inc 3)+ 1
→2*(3+ 1)+ 1
→2*4+1→9 I Voninnennachaußen(innermost-first):
inc (double (inc 3)) →inc (double (3+1))
→inc (2*(3+ 1))
→(2*(3+ 1))+ 1
→2*4+1→9
Auswertungsstrategien
addx :: String → String addx s = ’x ’ : s
double :: String→ String double s = s++ s I Reduktion vonaddx ( double (addx "y" )) I Vonaußennachinnen(outermost-first):
addx ( double (addx "y" )) →’x ’ : double (addx "y" )
→’x ’ : ( addx "y" ++ addx "y" )
→’x ’ : ( ( ’ x ’ : "y" ) ++ addx "y" )
→’x ’ : ( ( ’ x ’ : "y" ) ++ ( ’ x ’ : "y" ))
→"xxyxy"
I Voninnennachaußen(innermost-first):
addx ( double (addx "y" )) →addx ( double ( ’ x ’ : "y" ))
→addx ( double ( "xy" ))
→addx ("xy" ++ "xy" )
→addx "xyxy"
→’x ’ : "xyxy"→"xxyxy"
Konfluenz
I Sei→∗ die Reduktion in null oder mehr Schritten.
Definition (Konfluenz)
→∗ istkonfluentgdw:
Für aller,s,tmits←∗ r→∗ tgibt esuso dasss→∗ u←∗ t.
I Wenn wir von Laufzeitfehlern abstrahieren, gilt:
Theorem (Konfluenz)
Funktionale Programme sind für jede Auswertungsstrategiekonfluent.
PI3 WS 16/17 17 [38]
Termination und Normalform
Definition (Termination)
→istterminierendgdw. es keine unendlichen Ketten gibt:
t1→t2→t3→. . .tn→. . .
Theorem (Normalform)
Terminierendefunktionale Programme werten unter jeder Auswertungsstragie jeden Ausdruck zum gleichen Wert aus (der Normalform).
I Auswertungsstrategie fürnicht-terminierendeProgramme relevant.
I Nicht-Terminationnötig(Turing-Mächtigkeit)
PI3 WS 16/17 18 [38]
Auswirkung der Auswertungsstrategie
I Outermost-first entsprichtcall-by-need,verzögerteAuswertung.
I Innermost-first entsprichtcall-by-value,strikteAuswertung I Beispiel:
repeat :: Int→ String→ String repeat n s =i f n == 0then ""
else s ++ repeat (n−1) s undef :: String
undef = undef
I Auswertung vonrepeat 0 undef
PI3 WS 16/17 19 [38]
Striktheit
Definition (Striktheit)
Funktionf iststrikt ⇐⇒ Ergebnis ist undefiniert
sobald ein Argument undefiniert ist.
I DenotationelleEigenschaft (nicht operational)
I Java, C etc. sindcall-by-value(nach Sprachdefinition) und damitstrikt I Haskell istnicht-strikt(nach Sprachdefinition)
I repeat0 undefmuss""ergeben.
IMeistenImplementationennutzenverzögerte Auswertung I Fallunterscheidung istimmernicht-strikt.
PI3 WS 16/17 20 [38]
Datentypen
PI3 WS 16/17 21 [38]
Datentypen als Modellierungskonstrukt
ProgrammemanipuliereneinModell(der Umwelt)
I FunktionaleSicht:
Werte Funktionen Werte
I ImperativeSicht: Speicher Programm
I ObjektorientierteSicht: Methoden
Objekte
Speicher Speicher
Speicher
PI3 WS 16/17 22 [38]
Typkonstruktoren
I Aufzählungen
I Produkt
I Rekursion
I Funktionsraum
PI3 WS 16/17 23 [38]
Beispiel: Uncle Bob’s Auld-Time Grocery Shoppe
Ein Tante-Emma Laden wie in früheren Zeiten.
PI3 WS 16/17 24 [38]
Beispiel: Uncle Bob’s Auld-Time Grocery Shoppe
Äpfel Boskoop 55 ct/Stk
Cox Orange 60 ct/Stk Granny Smith 50 ct/Stk
Eier 20 ct/Stk
Käse Gouda 14,50 ¤/kg
Appenzeller 22.70 ¤/kg
Schinken 1.99 ¤/100 g
Salami 1.59 ¤/100 g
Milch 0.69 ¤/l
Bio 1.19 ¤/l
PI3 WS 16/17 25 [38]
Aufzählungen
I Aufzählungen: Menge vondisjunktenKonstanten Apfel={Boskoop,Cox,Smith}
Boskoop6=Cox,Cox6=Smith,Boskoop6=Smith
I GenaudreiunterschiedlicheKonstanten
I Funktion mitWertebereichApfelmuss drei Fälle unterscheiden I Beispiel:preis:Apfel→Nmit
preis(a) =
55 a=Boskoop 60 a=Cox 50 a=Smith
PI3 WS 16/17 26 [38]
Aufzählung und Fallunterscheidung in Haskell
I Definition
data Apfel = Boskoop | CoxOrange | GrannySmith
I ImpliziteDeklarationderKonstruktorenBoskoop :: ApfelalsKonstanten
I Großschreibungder Konstruktoren I Fallunterscheidung:
apreis :: Apfel → Int apreis a =casea of
Boskoop→55 CoxOrange→60 GrannySmith →50
data Farbe = Rot | Grn farbe :: Apfel→Farbe farbe d =
casedof
GrannySmith →Grn _→Rot
PI3 WS 16/17 27 [38]
Fallunterscheidung in der Funktionsdefinition
I Abkürzende Schreibweisen (syntaktischer Zucker):
f c1==e1 . . . f cn==en
−→
f x== casexofc1 → e1, . . . cn → en
I Damit:
apreis :: Apfel→ Int apreis Boskoop = 55 apreis CoxOrange = 60 apreis GrannySmith = 50
PI3 WS 16/17 28 [38]
Der einfachste Aufzählungstyp
I EinfachsteAufzählung: Wahrheitswerte Bool={False,True}
I Genau zwei unterschiedliche Werte I Definitionvon Funktionen:
I Wertetabellensind explizite Fallunterscheidungen
∧ true false true true false false false false
true ∧ true = true true ∧ false = false false ∧ true = false false ∧ false = false
PI3 WS 16/17 29 [38]
Wahrheitswerte: Bool
I Vordefiniertals
dataBool= False | True I VordefinierteFunktionen:
not :: Bool→ Bool −−Negation (&&) :: Bool→ Bool→Bool −−Konjunktion (| |) :: Bool→ Bool→Bool −−Disjunktion I Konjunktiondefiniert als
a && b =casea of False → False True→b I&&,| |sind rechtsnicht strikt
I1 == 0 && div 1 0 == 0→False
I i f _then_ else_als syntaktischer Zucker:
ifbthenpelseq −→casebof True → p False → q
PI3 WS 16/17 30 [38]
Produkte
I Konstruktoren könnenArgumentehaben I Beispiel: EinDatumbesteht ausTag,Monat,Jahr I Mathematisch: Produkt (Tupel)
Date = {Date (n, m, y)|n∈N,m∈Month,y∈N} Month = {Jan,Feb,Mar, . . .}
I Funktionsdefinition:
I Konstruktorargumente sindgebundene Variablen year(D(n,m,y)) = y
day(D(n,m,y)) = n
I Bei derAuswertungwirdgebundene Variabledurchkonkretes Argument ersetzt
Produkte in Haskell
I Konstruktoren mitArgumenten:
dataDate = Date Int Month Int
dataMonth = Jan | Feb | Mar | Apr |May | Jun
| Jul | Aug | Sep | Oct | Nov | Dec I Beispielwerte:
today = Date 25 Oct 2016 bloomsday = Date 16 Jun 1904
I ÜberFallunterscheidungZugriff aufArgumenteder Konstruktoren:
day :: Date→ Int year :: Date→ Int
day d =casedof Date t m y→t year (Date _ _ y) = y
Beispiel: Tag im Jahr
I 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 mwhere sumPrevMonths :: Month→ Int
sumPrevMonths Jan = 0
sumPrevMonths m = daysInMonth ( prev m) y + sumPrevMonths ( prev m) I Tage im Monat benötigt Jahr als Argument (Schaltjahr!)
daysInMonth :: Month→ Int→ Int prev :: Month→Month
I Schaltjahr: Gregorianischer Kalender leapyear :: Int→ Bool
leapyear y =i f mod y 100 == 0thenmod y 400 == 0 elsemod y 4 == 0
PI3 WS 16/17 33 [38]
Beispiel: Produkte in Bob’s Shoppe
I Käsesorten und deren Preise:
dataKaese = Gouda | Appenzeller kpreis :: Kaese→ Double kpreis Gouda = 1450 kpreis Appenzeller = 2270
I Alle Artikel:
data A r t i k e l = Apfel Apfel | Eier
| Kaese Kaese | Schinken
| Salami | Milch Bool
PI3 WS 16/17 34 [38]
Beispiel: Produkte in Bob’s Shoppe
I Mengenangaben:
dataMenge = Stueck Int | Gramm Int
| Kilo Double | L i t e r Double I Der Preis und seine Berechnung:
data Preis = Cent Int | Ungueltig p r e i s :: A r t i k e l →Menge→ Preis
p r e i s ( Apfel a) (Stueck n) = Cent (n∗ apreis a) p r e i s Eier (Stueck n) = Cent (n∗ 20) p r e i s (Kaese k)( Kilo kg) = Cent (round(kg∗
kpreis k)) p r e i s Schinken (Gramm g) = Cent (g/100∗ 199) p r e i s Salami (Gramm g) = Cent (g/100∗ 159) p r e i s (Milch bio ) ( L i t e r l ) =
Cent (round ( l∗ i f not bio then 69 else 119))
p r e i s _ _ = Ungueltig
PI3 WS 16/17 35 [38]
Auswertung der Fallunterscheidung
I Argument der Fallunterscheidung wirdnur soweit nötigausgewertet I Beispiel:
dataFoo = Foo Int | Bar f :: Foo→Int
f foo =casefoo ofFoo i → i ; Bar→0 g :: Foo→Int
g foo =casefoo ofFoo i →9; Bar →0 I Auswertungen:
f Bar → 0
f (Foo undefined ) → ∗∗∗ Exception : undefined
g Bar → 0
g (Foo undefined ) → 9
PI3 WS 16/17 36 [38]
Der Allgemeine Fall: Algebraische Datentypen
Definition einesalgebraischen DatentypenT:
data T = C1t1,1. . .t1,k1
| C2t2,1. . .t2,k2
. . .
| Cntn,1. . .tn,kn
1.KonstruktorenC1, . . . ,Cnsinddisjunkt:
Cix1. . .xn= Cjy1. . .ym=⇒i=j 2.Konstruktorensindinjektiv:
C x1. . .xn= C y1. . .yn=⇒xi= yi 3.Konstruktorenerzeugenden Datentyp:
∀x∈T.x= Ciy1. . .ym Diese Eigenschaften machenFallunterscheidungmöglich.
Rekursion?−→Nächste Vorlesung!
PI3 WS 16/17 37 [38]
Zusammenfassung
I Striktheit
IHaskell istspezifiziertals nicht-strikt I Datentypen und Funktionsdefinitiondual
IAufzählungen—Fallunterscheidung
IProdukte— Projektion I Algebraische Datentypen
IDreiwesentlicheEigenschaftender Konstruktoren I Nächste Vorlesung: Rekursive Datentypen
PI3 WS 16/17 38 [38]