Handzettel - FB3 - Uni Bremen

Werbung
Inhalt
I
Praktische Informatik 3: Einführung in die Funktionale
Programmierung
Vorlesung vom 03.11.2010: Funktionen und Datentypen
Auswertungsstrategien
I
I
Definition von Funktionen
I
Christoph Lüth & Dennis Walter
I
Universität Bremen
Wintersemester 2010/11
I
I
Aufzählungen
I
Produkte
Basisdatentypen:
Wahrheitswerte, numerische Typen, alphanumerische Typen
2 [36]
1 [36]
Fahrplan
I
Syntaktische Feinheiten
Definition von Datentypen
I
Rev. 1167
Striktheit
Auswertungsstrategien
Teil I: Funktionale Programmierung im Kleinen
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
double x = 2∗x
I
Einführung
I
Funktionen und Datentypen
I
Reduktion von inc (double (inc 3))
I
Rekursive Datentypen
I
I
Typvariablen und Polymorphie
I
Funktionen höherer Ordnung
I
Typinferenz
Von außen nach innen (outermost-first):
inc (double (inc 3))
double (inc 3)+ 1
2*(inc 3)+ 1
2*(3+ 1)+ 1
2*4+1
9
I
Von innen nach außen (innermost-first):
inc (double (inc 3))
inc (double (3+1))
inc (2*(3+ 1))
(2*(3+ 1))+ 1
2*4+1
9
I
Teil II: Funktionale Programmierung im Großen
I
Teil III: Funktionale Programmierung im richtigen Leben
4 [36]
3 [36]
Auswertungsstrategien und Konfluenz
Auswirkung der Auswertungsstrategie
I
Outermost-first entspricht call-by-need, verzögerte Auswertung.
Funktionale Programme sind für jede Auswertungsstrategie konfluent.
I
Innermost-first entspricht call-by-value, strikte Auswertung
Theorem (Normalform)
I
Beispiel:
Theorem (Konfluenz)
Terminierende funktionale Programme werten unter jeder
Auswertungsstragie jeden Ausdruck zum gleichen Wert aus (der
Normalform).
I
Auswertungsstrategie für nicht-terminierende Programme relevant.
I
Nicht-Termination nötig (Turing-Mächtigkeit)
div
::
Int → Int → Int
Ganzzahlige Division, undefiniert für div n 0
mult :: I n t → I n t → I n t
mult n m = i f n == 0 then 0
e l s e ( mult ( n− 1 ) m)+ m
I
Auswertung von mult 0 (div 1 0)
5 [36]
Striktheit
Wie definiere ich eine Funktion?
Generelle Form:
Definition (Striktheit)
Funktion f ist strikt
6 [36]
I
⇐⇒
Signatur:
Ergebnis ist undefiniert
sobald ein Argument undefiniert ist
I
Semantische Eigenschaft (nicht operational)
I
Standard ML, Java, C etc. sind strikt (nach Sprachdefinition)
I
Haskell ist nicht-strikt (nach Sprachdefinition)
max ::
I
Int → Int → Int
Definition
max x y = i f x < y then y e l s e x
I
I
I
Kopf, mit Parametern
I
Rumpf (evtl. länger, mehrere Zeilen)
I
Typisches Muster: Fallunterscheidung, dann rekursiver Aufruf
I
Was gehört zum Rumpf (Geltungsberereich)?
Meisten Implementationen nutzen verzögerte Auswertung
Fallunterscheidung ist immer nicht-strikt
7 [36]
8 [36]
Haskell-Syntax: Charakteristika
I
I
Geltungsbereich der Definition von f:
alles, was gegenüber f eingerückt ist.
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
Keine Klammern
Abseitsregel: Gültigkeitsbereich durch Einrückung
I
I
Wichtigstes Zeichen:
Funktionsapplikation: f a
I
I
Funktionsdefinition:
f x1 x2 . . . xn = E
Leichtgewichtig
I
I
Haskell-Syntax I: Die Abseitsregel
Keine Klammern
I
Gilt auch verschachtelt.
I
Kommentare sind passiv
Auch in anderen Sprachen (Python, Ruby)
9 [36]
Haskell-Syntax II: Kommentare
I
I
Haskell-Syntax III: Bedingte Definitionen
I
Pro Zeile: Ab −− bis Ende der Zeile
f x y = irgendwas
10 [36]
f x y = i f B1 then P e l s e
i f B2 then Q e l s e . . .
−− und hier der Kommentar!
. . . bedingte Gleichungen:
Über mehrere Zeilen: Anfang {-, Ende -}
f x y
| B1 = . . .
| B2 = . . .
{−
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 über mehrere Z e i l e n
bis hier
f x y = irgendwas
I
Statt verschachtelter Fallunterscheidungen . . .
−}
I
Auswertung der Bedingungen von oben nach unten
I
Wenn keine Bedingung wahr ist: Laufzeitfehler! Deshalb:
Kann geschachtelt werden.
| otherwise =...
11 [36]
Haskell-Syntax IV: Lokale Definitionen
I
Datentypen als Modellierungskonstrukt
Programme manipulieren ein Modell (der Umwelt)
Lokale Definitionen mit where oder let:
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
i f g then P y
else Q
I
f, y, . . . werden gleichzeitig definiert (Rekursion!)
I
Namen f, y und Parameter (x) überlagern andere
I
Es gilt die Abseitsregel
I
12 [36]
I
Funktionale Sicht:
I
Imperative Sicht:
I
Objektorientierte Sicht:
Deshalb: Auf gleiche Einrückung der lokalen Definition achten!
13 [36]
Datentypen, Funktionen und Beweise
I
Datentypen konstruieren Werte
I
Funktionen definieren Berechnungen
I
Berechnungen haben Eigenschaften
I
Dualität:
14 [36]
Typkonstruktoren
Datentypkonstruktor ←→ Definitionskonstrukt ←→ Beweiskonstrukt
15 [36]
I
Aufzählungen
I
Produkt
I
Rekursion
I
Funktionsraum
16 [36]
Aufzählungen
Aufzählung und Fallunterscheidung in Haskell
I
I
Aufzählungen: Menge von disjunkten Konstanten
data Days = Mon | Tue | Wed | Thu | F r i | S a t | Sun
Days = {Mon, Tue, Wed, Thu, Fri, Sat, Sun}
I
I
Mon 6= Tue, Mon 6= Wed, Tue 6= Thu, Wed 6= Sun . . .
I
I
Genau sieben unterschiedliche Konstanten
I
Funktion mit Wertebereich Days muss sieben Fälle unterscheiden
I
Beispiel: weekend : Days → Bool mit
weekend(d) =
Definition
Implizite Deklaration der Konstruktoren Mon :: Days als Konstanten
Großschreibung der Konstruktoren
Fallunterscheidung:
weekend :: Days → Bool
weekend d = case 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
Fri → False


 true
d = Sat ∨ d = Sun
false d = Mon ∨ d = Tue ∨ d = Wed ∨


d = Thu ∨ d = Fri
weekend d =
case d o f
S a t → True
Sun → True
_
→ False
17 [36]
Fallunterscheidung in der Funktionsdefinition
I
Der einfachste Aufzählungstyp
I
Abkürzende Schreibweise (syntaktischer Zucker):
f c1 == e1
...
f cn == en
18 [36]
Einfachste Aufzählung: Wahrheitswerte
Bool = {True, False}
f x == case x of c1 → e1 ,
...
cn → en
−→
I
I
I
Damit:
Definition von Funktionen:
I
weekend :: Days → Bool
weekend S a t = True
weekend Sun = True
weekend _
= False
Genau zwei unterschiedliche Werte
Wertetabellen sind explizite Fallunterscheidungen
∧
true
false
true
true
false
true
true
false
false
false
false
false
∧
∧
∧
∧
true
false
true
false
=
=
=
=
true
false
false
false
19 [36]
Wahrheitswerte: Bool
I
20 [36]
Beispiel: Ausschließende Disjunktion
Vordefiniert als
I
data Bool = True | F a l s e
I
I
exOr :: Bool → Bool → Bool
exOr x y = ( x | | y ) && ( n o t ( x && y ) )
Vordefinierte Funktionen:
not
&&
||
::
::
::
Bool → Bool
Bool → Bool → Bool
Bool → Bool → Bool
−− Negation
−− Konjunktion
−− Disjunktion
I
Konjunktion definiert als
I
&&, || sind rechts nicht strikt
I
I
1 ==0 && div 1 0 ==0
Alternative 1: explizite Wertetabelle:
exOr
exOr
exOr
exOr
a && b = case a o f True → b
False → False
I
Mathematische Definiton:
False
True
False
True
False
False
True
True
=
=
=
=
False
True
True
False
Alternative 2: Fallunterscheidung auf ersten Argument
exOr True y = n o t y
exOr F a l s e y = y
False
if then else als syntaktischer Zucker:
I
if b then p else q −→ case b of True → p
False → q
Was ist am besten?
I
Effizienz, Lesbarkeit, Striktheit
21 [36]
Produkte
I
I
I
22 [36]
Produkte in Haskell
Konstruktoren können Argumente haben
Beispiel: Ein Datum besteht aus Tag, Monat, Jahr
Mathematisch: Produkt (Tupel)
I
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
Date = {Date (n, m, y) | n ∈ N, m ∈ Month, y ∈ N}
Month = {Jan, Feb, Mar, . . .}
I
I
Konstruktorargumente sind gebundene Variablen
I
year (D(n, m, y )) = y
Über Fallunterscheidung Zugriff auf Argumente der Konstruktoren:
day
:: Date → I n t
y e a r :: Date → I n t
day d = case d o f Date t m y → t
y e a r ( Date d m y ) = y
day (D(n, m, y )) = n
I
Beispielwerte:
today
= Date 5 Nov 2008
b l o o m s d a y = Date 16 Jun 1904
Funktionsdefinition:
I
Konstruktoren mit Argumenten
Bei der Auswertung wird gebundene Variable durch konkretes Argument
ersetzt
23 [36]
24 [36]
Beispiel: Tag im Jahr
I
Fallunterscheidung und Produkte
Tag im Jahr: Tag im laufenden Monat plus Summe der Anzahl der
Tage der vorherigen Monate
I
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
= day sI nM onth ( p r e v m) y +
sumPrevMonths ( p r e v m)
I
Dreieck, gegeben durch Kantenlänge
I
Kreis, gegeben durch Radius
I
Rechteck, 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 Double | C i r c l e Double | R e c t Double Double
Tage im Monat benötigt Jahr als Argument (Schaltjahr!)
I
da ysI nMonth :: Month → I n t → I n t
p r e v :: Month → Month
I
Beispiel: geometrische Objekte
I
Berechung des Umfangs:
c i r c :: Obj → Double
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 )
Schaltjahr: Gregorianischer Kalender
l e a p y e a r :: I n t → Bool
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
26 [36]
25 [36]
Der Allgemeine Fall: Algebraische Datentypen
Beweis von Eigenschaften
Definition eines algebraischen Datentypen T:
data T = C1 t1,1 . . . t1,k1
...
| Cn tn,1 . . . tn,kn
I
I
Konstruktoren C1 , . . . , Cn sind disjunkt:
Ci x1 . . . xn = Cj y1 . . . ym −→ i = j
I
Konstruktoren sind injektiv:
C x1 . . . xn = C y1 . . . yn −→ xi = yi
I
Konstruktoren erzeugen den Datentyp:
∀x ∈ T . x = Ci y1 . . . ym
Eigenschaften von Programmen: Prädikate
I
Haskell-Ausdrücke vom Typ Bool
I
Allquantifizierte Aussagen:
wenn P(x ) Prädikat, dann ist ∀x .P(x ) auch ein Prädikat
I
Sonderfall Gleichungen s == t
I
Müssen nicht ausführbar sein
Diese Eigenschaften machen Fallunterscheidung möglich.
27 [36]
Wie beweisen?
28 [36]
Ein ganz einfaches Beispiel
I
Gleichungsumformung (equational reasoning)
I
Fallunterscheidungen
I
Induktion
I
Wichtig: formale Notation
addTwice :: I n t → I n t → I n t
addTwice x y = 2 ∗ ( x+ y )
Lemma: addTwice x (y + z) = addTwice (x + y ) z
addTwice x (y + z)
= 2 ∗ (x + (y + z))
— Def. addTwice
= 2 ∗ ((x + y ) + z)
— Assoziativität von +
= addTwice (x + y ) z — Def. addTwice
30 [36]
29 [36]
Fallunterscheidung
Das Rechnen mit Zahlen
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: max x y − min x
max x y − min x
• Fall: x < y
= y − min x y
= y −x
= |x − y |
• Fall: x ≥ y
= x − min x y
= x −y
= |x − y |
= |x − y |
Beschränkte Genauigkeit,
beliebige Genauigkeit,
←→
konstanter Aufwand
wachsender Aufwand
y = |x − y |
y
Haskell bietet die Auswahl:
— Def. max
— Def. min
— Wenn x < y , dann y − x = |x − y |
I
Int - ganze Zahlen als Maschinenworte (≥ 31 Bit)
I
Integer - beliebig große ganze Zahlen
— Def. max
— Def. min
— Wenn x ≥ y , dann x − y = |x − y |
I
Rational - beliebig genaue rationale Zahlen
I
Float, Double - Fließkommazahlen (reelle Zahlen)
31 [36]
32 [36]
Ganze Zahlen: Int und Integer
I
Fließkommazahlen: Double
I
Nützliche Funktionen (überladen, auch für Integer):
+, ∗ , ^ , −
abs
div , quot
mod , rem
::
::
::
::
Int →
Int →
Int →
Int →
Doppeltgenaue Fließkommazahlen (IEEE 754 und 854)
I
Int → Int
I n t −− Betrag
Int → Int
Int → Int
I
Logarithmen, Wurzel, Exponentation, π und e, trigonometrische
Funktionen
Konversion in ganze Zahlen:
I
fromIntegral :: Int, Integer-> Double
I
fromInteger :: Integer-> Double
Es gilt (div x y)*y + mod x y == x
I
Vergleich durch ==, /=, <=, <, . . .
I
round, truncate :: Double-> Int, Integer
I
Achtung: Unäres Minus
I
Überladungen mit Typannotation auflösen:
I
Unterschied zum Infix-Operator -
I
Im Zweifelsfall klammern: abs (-34)
round ( f r o m I n t 10)
I
::
Int
Rundungsfehler!
33 [36]
Alphanumerische Basisdatentypen: Char
34 [36]
Zusammenfassung
I
I
I
I
Nützliche Funktionen:
ord
chr
::
::
Striktheit
I
Notation für einzelne Zeichen: ’a’,. . .
I
I
Char → I n t
I n t → Char
I
::
::
::
::
Char →
Char →
Char →
Char →
Char
Char
Bool
Bool
I
I
I
I
Beweis durch Gleichungsumformung
Programmeigenschaften als Prädikate
Fallunterscheidung als Beweiskonstrukt
Wahrheitswerte Bool
Numerische Basisdatentypen:
I
I
Aufzählungen — Fallunterscheidung
Produkte
Funktionsdefinition und Beweis dual
I
toLower
toUpper
isDigit
isAlpha
Haskell ist spezifiziert als nicht-strikt
Datentypen und Funktionsdefinition dual
Int, Integer, Rational und Double
Zeichenketten: String
35 [36]
I
Alphanumerische Basisdatentypen: Char
I
Nächste Vorlesung: Rekursive Datentypen
36 [36]
Herunterladen