Praktische Informatik 3: Einführung in die Funktionale Programmierung
Vorlesung vom 03.11.2010: Funktionen und Datentypen
Christoph Lüth & Dennis Walter Universität Bremen Wintersemester 2010/11
Rev. 1167 1 [36]
Inhalt
I Auswertungsstrategien
IStriktheit
I Definition vonFunktionen
ISyntaktischeFeinheiten I Definition vonDatentypen
IAufzählungen
IProdukte I Basisdatentypen:
IWahrheitswerte, numerische Typen, alphanumerische Typen
2 [36]
Fahrplan
ITeil I: Funktionale Programmierung im Kleinen
IEinführung
IFunktionen und Datentypen
IRekursive Datentypen
ITypvariablen und Polymorphie
IFunktionen höherer Ordnung
ITypinferenz
ITeil II: Funktionale Programmierung im Großen ITeil III: Funktionale Programmierung im richtigen Leben
3 [36]
Auswertungsstrategien
i n c :: I n t → I n t i n c x = x+ 1
d o u b l e :: I n t → I n t d o u b l e 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
4 [36]
Auswertungsstrategien und Konfluenz
Theorem (Konfluenz)
Funktionale Programme sind für jede Auswertungsstrategiekonfluent.
Theorem (Normalform)
Terminierendefunktionale Programme werten unter jeder Auswertungsstragie jeden Ausdruck zum gleichen Wert aus (der Normalform).
IAuswertungsstrategie fürnicht-terminierendeProgramme relevant.
INicht-Termination nötig (Turing-Mächtigkeit)
5 [36]
Auswirkung der Auswertungsstrategie
I Outermost-first entsprichtcall-by-need,verzögerteAuswertung.
I Innermost-first entsprichtcall-by-value,strikteAuswertung I Beispiel:
d i v :: I n t→ I n t→ I n t
Ganzzahlige Division, undefiniert fürdiv n 0 m u l t :: I n t→ I n t→ I n t
m u l t n m= i f n == 0 then 0 e l s e ( m u l t ( n− 1 ) m)+m
IAuswertung vonmult 0 (div 1 0)
6 [36]
Striktheit
Definition (Striktheit)
Funktionf iststrikt ⇐⇒ Ergebnis ist undefiniert
sobald ein Argument undefiniert ist
ISemantischeEigenschaft (nicht operational)
IStandard ML, Java, C etc. sindstrikt(nach Sprachdefinition) IHaskell istnicht-strikt(nach Sprachdefinition)
IMeistenImplementationennutzenverzögerte Auswertung IFallunterscheidung istimmernicht-strikt
7 [36]
Wie definiere ich eine Funktion?
Generelle Form:
I Signatur:
max :: I n t→ I n t→ I n t I Definition
max x y = i f x < y then y e l s e x
IKopf, mit Parametern
IRumpf(evtl. länger, mehrere Zeilen)
ITypischesMuster: Fallunterscheidung, dann rekursiver Aufruf
IWas gehört zum Rumpf (Geltungsberereich)?
8 [36]
Haskell-Syntax: Charakteristika
ILeichtgewichtig
IWichtigstes Zeichen:
IFunktionsapplikation:f a
IKeineKlammern
IAbseitsregel: Gültigkeitsbereich durch Einrückung
IKeineKlammern
IAuch in anderenSprachen(Python, Ruby)
9 [36]
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 f a e n g t s an und h i e r g e h t s w e i t e r
immer w e i t e r
g y z = und h i e r f a e n g t was n e u e s an I Gilt auchverschachtelt.
I Kommentare sindpassiv
10 [36]
Haskell-Syntax II: Kommentare
IPro Zeile: Ab−−bis Ende der Zeile
f x y = i r g e n d w a s −−und hier der Kommentar!
IÜber mehrere Zeilen: Anfang{-, Ende-}
{−
H i e r f ä n g t d e r Kommentar an e r s t r e c k t s i c h ü b e r m e h r e r e Z e i l e n
b i s h i e r −}
f x y = i r g e n d w a s
IKann geschachtelt werden.
11 [36]
Haskell-Syntax III: Bedingte Definitionen
I Statt verschachtelter Fallunterscheidungen . . . f x y = i f B1 then P e l s e
i f B2 then Q e l s e. . . . . .bedingte Gleichungen:
f x y
| B1 =. . .
| B2 =. . .
I Auswertung der Bedingungen von oben nach unten I Wenn keine Bedingung wahr ist:Laufzeitfehler! Deshalb:
| o t h e r w i s e =. . .
12 [36]
Haskell-Syntax IV: Lokale Definitionen
ILokale Definitionen mitwhereoderlet:
f x y
| g =P y
| o t h e r w i s e = Q where
y =M f x =N x
f x y= l e t y =M
f x =N x i n i f g then P y
e l s e Q
If,y, . . . werdengleichzeitigdefiniert (Rekursion!) INamenf,yund Parameter (x)überlagernandere IEs gilt dieAbseitsregel
IDeshalb:Aufgleiche Einrückungder lokalen Definition achten!
13 [36]
Datentypen als Modellierungskonstrukt
ProgrammemanipuliereneinModell(der Umwelt)
I FunktionaleSicht:
I ImperativeSicht:
I ObjektorientierteSicht:
14 [36]
Datentypen, Funktionen und Beweise
IDatentypen konstruierenWerte
IFunktionen definierenBerechnungen
IBerechnungen habenEigenschaften
IDualität:
Datentypkonstruktor←→Definitionskonstrukt←→Beweiskonstrukt
15 [36]
Typkonstruktoren
I Aufzählungen
I Produkt
I Rekursion
I Funktionsraum
16 [36]
Aufzählungen
IAufzählungen: Menge vondisjunktenKonstanten Days={Mon,Tue,Wed,Thu,Fri,Sat,Sun}
Mon6=Tue,Mon6=Wed,Tue6=Thu,Wed6=Sun. . .
IGenausiebenunterschiedlicheKonstanten
IFunktion mitWertebereichDaysmuss sieben Fälle unterscheiden IBeispiel:weekend:Days→Boolmit
weekend(d) =
true d=Sat∨d=Sun
false d=Mon∨d=Tue∨d=Wed∨ d=Thu∨d=Fri
17 [36]
Aufzählung und Fallunterscheidung in Haskell
I Definition
data Days =Mon | Tue | Wed | Thu | F r i | S a t | Sun
IImpliziteDeklarationderKonstruktorenMon :: DaysalsKonstanten
IGroßschreibungder Konstruktoren I Fallunterscheidung:
weekend :: Days → B o o l weekend d = c a s e d o f
S a t → True
Sun → True
Mon → F a l s e Tue → F a l s e Wed → F a l s e Thu → F a l s e F r i → F a l s e
weekend d = c a s e d o f
S a t → True
Sun → True
_ → F a l s e
18 [36]
Fallunterscheidung in der Funktionsdefinition
IAbkürzende Schreibweise (syntaktischer Zucker):
f c1==e1 . . . f cn==en
−→
f x==casexofc1 → e1, . . . cn → en
IDamit:
weekend :: Days → B o o l weekend S a t = True weekend Sun = True weekend _ = F a l s e
19 [36]
Der einfachste Aufzählungstyp
I EinfachsteAufzählung: Wahrheitswerte Bool={True,False}
IGenau zwei unterschiedliche Werte I Definitionvon Funktionen:
IWertetabellensind explizite Fallunterscheidungen
∧ true false true true false false false false
true ∧ true = true true ∧ false = false false ∧ true = false false ∧ false = false
20 [36]
Wahrheitswerte: Bool
IVordefiniertals
data B o o l = True | F a l s e IVordefinierteFunktionen:
n o t :: B o o l→ B o o l −−Negation
&& :: B o o l→ B o o l→ B o o l −−Konjunktion
| | :: B o o l→ B o o l→ B o o l −−Disjunktion IKonjunktiondefiniert als
a && b = c a s e a o f True → b F a l s e → F a l s e I&&,||sind rechtsnicht strikt
I1==0 && div 1 0==0 False Iif then elseals syntaktischer Zucker:
ifbthenpelseq −→casebof True → p False → q
21 [36]
Beispiel: Ausschließende Disjunktion
I Mathematische Definiton:
exOr :: B o o l→ B o o l→ B o o l
exOr x y = ( x | | y ) && ( n o t ( x && y ) ) I Alternative 1:explizite Wertetabelle:
exOr F a l s e F a l s e = F a l s e exOr True F a l s e = True exOr F a l s e True = True exOr True True = F a l s e
I Alternative 2:Fallunterscheidungauf ersten Argument exOr True y = n o t y
exOr F a l s e y = y I Was ist ambesten?
IEffizienz, Lesbarkeit, Striktheit
22 [36]
Produkte
IKonstruktoren könnenArgumentehaben IBeispiel: EinDatumbesteht ausTag,Monat,Jahr IMathematisch: Produkt (Tupel)
Date = {Date (n, m, y)|n∈N,m∈Month,y∈N} Month = {Jan,Feb,Mar, . . .}
IFunktionsdefinition:
IKonstruktorargumente sindgebundene Variablen year(D(n,m,y)) = y
day(D(n,m,y)) = n
IBei derAuswertungwirdgebundene Variabledurchkonkretes Argument ersetzt
23 [36]
Produkte in Haskell
I Konstruktoren mitArgumenten
data Date = Date I n t Month I n t
data Month = Jan | Feb | Mar | Apr | May | Jun
| J u l | Aug | Sep | Oct | Nov | Dec I Beispielwerte:
t o d a y =Date 5 Nov 2008 b l o o m s d a y =Date 16 Jun 1904
I ÜberFallunterscheidungZugriff aufArgumenteder Konstruktoren:
day :: Date→ I n t y e a r :: Date→ I n t
day d = c a s e d o f Date t m y→ t y e a r ( Date d m y ) =y
24 [36]
Beispiel: Tag im Jahr
ITag im Jahr: Tag im laufenden Monat plus Summe der Anzahl der Tage der vorherigen Monate
y e a r D a y :: Date→ I n t
y e a r D a y ( Date d m y ) = d +sumPrevMonths m where sumPrevMonths :: Month→ I n t
sumPrevMonths Jan =0
sumPrevMonths m = d a y s I n M o n t h ( p r e v m) y + sumPrevMonths ( p r e v m) ITage im Monat benötigt Jahr als Argument (Schaltjahr!)
d a y s I n M o n t h :: Month→ I n t→ I n t p r e v :: Month→ Month
ISchaltjahr: Gregorianischer Kalender l e a p y e a r :: I n t→ B o o l
l e a p y e a r y = i f mod y 100 == 0 then mod y 400 == 0 e l s e mod y 4 == 0
25 [36]
Fallunterscheidung und Produkte
I Beispiel: geometrische Objekte
IDreieck, gegeben durch Kantenlänge
IKreis, gegeben durch Radius
IRechteck, gegeben durch zwei Kantenlängen
O={Tri(a)|a∈R} ∪ {Circle(r)|r∈R} ∪ {Rect(a,b)|a,b∈R}
data Obj = T r i D o u b l e | C i r c l e D o u b l e | R e c t D o u b l e D o u b l e I Berechung desUmfangs:
c i r c :: Obj→ D o u b l e c i r c ( T r i a ) = 3∗ a c i r c ( C i r c l e r )= 2∗ p i∗ r c i r c ( R e c t a b )= 2∗( a+b )
26 [36]
Der Allgemeine Fall: Algebraische Datentypen
Definition einesalgebraischen DatentypenT:
data T= C1t1,1. . .t1,k1
. . .
| Cntn,1. . .tn,kn IKonstruktorenC1, . . . ,Cnsinddisjunkt:
Cix1. . .xn=Cjy1. . .ym−→i=j IKonstruktorensindinjektiv:
C x1. . .xn=C y1. . .yn−→xi=yi IKonstruktorenerzeugenden Datentyp:
∀x∈T.x=Ciy1. . .ym Diese Eigenschaften machenFallunterscheidungmöglich.
27 [36]
Beweis von Eigenschaften
I Eigenschaften von Programmen:Prädikate
IHaskell-Ausdrücke vom TypBool
IAllquantifizierte Aussagen:
wennP(x)Prädikat, dann ist∀x.P(x)auch ein Prädikat
ISonderfall Gleichungens == t
IMüssen nichtausführbarsein
28 [36]
Wie beweisen?
IGleichungsumformung(equational reasoning)
IFallunterscheidungen
IInduktion
IWichtig:formale Notation
29 [36]
Ein ganz einfaches Beispiel
ad dTwi ce :: I n t→ I n t→ I n t ad dTwi ce x y = 2∗( x+ y )
Lemma: addTwicex(y+z) =addTwice(x+y)z addTwicex(y+z)
= 2∗(x+ (y+z)) — Def.addTwice
= 2∗((x+y) +z) — Assoziativität von+
= addTwice(x+y)z — Def.addTwice
30 [36]
Fallunterscheidung
max , min :: I n t→ I n t→ I n t max x y = i f x < y then y e l s e x min x y = i f x < y then x e l s e y
Lemma: maxx y−minx y=|x−y|
maxx y−minx y
• Fall:x<y
= y−minx y — Def.max
= y−x — Def.min
= |x−y| — Wennx<y, danny−x=|x−y|
• Fall:x≥y
= x−minx y — Def.max
= x−y — Def.min
= |x−y| — Wennx≥y, dannx−y=|x−y|
= |x−y|
31 [36]
Das Rechnen mit Zahlen
BeschränkteGenauigkeit,
konstanterAufwand ←→ beliebigeGenauigkeit, wachsenderAufwand
Haskell bietet die Auswahl:
I Int- ganze Zahlen als Maschinenworte (≥31 Bit) I Integer- beliebig große ganze Zahlen
I Rational- beliebig genaue rationale Zahlen I Float,Double- Fließkommazahlen (reelle Zahlen)
32 [36]
Ganze Zahlen: Int und Integer
INützliche Funktionen (überladen, auch fürInteger):
+, ∗, ^ , − :: I n t→ I n t→ I n t a b s :: I n t→ I n t −−Betrag d i v , q u o t :: I n t→ I n t→ I n t mod , rem :: I n t→ I n t→ I n t Es gilt(div x y)*y + mod x y == x IVergleich durch==,/=,<=,<, . . . IAchtung:Unäres Minus
IUnterschied zum Infix-Operator-
IIm Zweifelsfall klammern:abs (-34)
33 [36]
Fließkommazahlen: Double
I Doppeltgenaue Fließkommazahlen (IEEE 754 und 854)
ILogarithmen, Wurzel, Exponentation,πunde, trigonometrische Funktionen
I Konversion in ganze Zahlen:
IfromIntegral :: Int, Integer-> Double
IfromInteger :: Integer-> Double
Iround, truncate :: Double-> Int, Integer
IÜberladungen mit Typannotation auflösen:
r o u n d ( f r o m I n t 1 0 ) :: I n t I Rundungsfehler!
34 [36]
Alphanumerische Basisdatentypen: Char
INotation für einzelneZeichen: ’a’,. . . INützlicheFunktionen:
o r d :: Char → I n t c h r :: I n t → Char t o L o w e r :: Char→ Char t o U p p e r :: Char→ Char i s D i g i t :: Char→ B o o l i s A l p h a :: Char→ B o o l
IZeichenketten: String
35 [36]
Zusammenfassung
I Striktheit
IHaskell istspezifiziertals nicht-strikt I Datentypen und Funktionsdefinitiondual
IAufzählungen—Fallunterscheidung
IProdukte
I Funktionsdefinition und Beweisdual
IBeweis durchGleichungsumformung
IProgrammeigenschaften alsPrädikate
IFallunterscheidungals Beweiskonstrukt I WahrheitswerteBool
I Numerische Basisdatentypen:
IInt,Integer,RationalundDouble I Alphanumerische Basisdatentypen:Char I Nächste Vorlesung: Rekursive Datentypen
36 [36]