Grundlagen der Programmierung 2 (1.C)

Werbung
Grundlagen der Programmierung 2
(1.C)
Prof. Dr. Manfred Schmidt-Schauÿ
Künstliche Intelligenz und Softwaretechnologie
3. Mai 2006
Funktionen auf Listen: map
map :: (a -> b) -> [a] -> [b]
map f []
= []
map f (x:xs)
= (f x) : (map f xs)
map wendet eine Funktion f auf alle Elemente einer Liste an
konstruiert Liste der Ergebnisse.
[] und (x:xs) links sind Muster(Pattern)
Grundlagen der Programmierung 2 (1.C)
- 1 -
Funktionen auf Listen: Beispiele
map f []
map f (x:xs)
= []
= (f x) : (map f xs)
map quadrat (1:(2:[]))
quadrat 1 : map quadrat (2:[])
1*1 : map quadrat (2:[])
1 : map quadrat (2:[])
1 : (quadrat 2 : map quadrat [])
1 : (2*2 : map quadrat [])
1 : (4 : map quadrat [])
1 : (4 : [])
Grundlagen der Programmierung 2 (1.C)
Zweite Gleichung
[quadrat/f,1/x,(2:[])/xs]
Interpreter will alles auswerten: deshalb
Zweite Gleichung
wg Interpreter
Erste Gleichung
= [1,4]
- 2 -
Auswertung: Wieviel ist nötig?
istLeer []
= True
istLeer (x:xs) = False
zahlenAb n
= n: zahlenAb (n+1)
Auswertung
istLeer [1..]
istLeer (zahlenAb 1)
istLeer (1: zahlenAb (1+1))
False
Grundlagen der Programmierung 2 (1.C)
verwende zahlenAb
Zweite Gleichung von istLeer
- 3 -
Listenfunktionen und Listenerzeuger
*Main> map quadrat [1..10]
[1,4,9,16,25,36,49,64,81,100]
*Main> map quadrat [1..]
[1,4,9,16,25,36,49,64,81,100,121, ....
Der Listenerzeuger [1..] erzeugt soviel von der Liste [1,2,3,4,5, usw.
wie von der Listenfunktion benötigt wird.
Grundlagen der Programmierung 2 (1.C)
- 4 -
Typen von Listenausdrücken
mapQuadrat xs = map quadrat
xs
mapQuadrat :: forall a. (Num a) => [a] -> [a]
mapLength xs = map length
xs
mapLength :: forall a. [[a]] -> [Int]
Grundlagen der Programmierung 2 (1.C)
- 5 -
Listenfunktion append
Die folgende Funktion hängt zwei Listen zusammen:
append :: [a] -> [a] -> [a]
append [] ys
= ys
append (x:xs) ys = x : (append xs ys)
Haskell-Operator: ++ und Infix
Haskell-Schreibweise: [1,2,3] ++ [4,5,6,7]
Grundlagen der Programmierung 2 (1.C)
- 6 -
Beispiele
Main> [] ++ [3,4,5]
[3,4,5]
Main> [0,1,2] ++ []
[0,1,2]
Main> [0,1,2] ++ [3,4,5]
[0,1,2,3,4,5]
Main> [0..10000] ++ [10001..20000] == [0..20000]
True
Grundlagen der Programmierung 2 (1.C)
- 7 -
Funktionen auf Listen (2)
Filtern von Elementen aus einer Liste:
(a -> Bool) -> [a] -> [a]
filter f []
= []
filter f (x:xs)
= if (f x) then x : filter f xs
else filter f xs
Beispiele:
filter (< 5) [1..10]
[1,2,3,4]
*Main> filter primzahlq [2..]
[2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,53,59,61,67,71,
73,79,83,89,97,101,103,107,109,113,127,131,137,139,
149,151,157,163,167,173,179,181,191,193,197,199,211,
Grundlagen der Programmierung 2 (1.C)
- 8 -
Funktionen auf Listen
Die ersten n Elemente der Liste xs:
take
take
take
take
:: Int -> [a] -> [a]
0 _
= []
n []
= []
n (x:xs) = x : (take (n-1) xs)
*Main> take 10 [20..40]
[20,21,22,23,24,25,26,27,28,29]
*Main> take 10 [20,23..]
[20,23,26,29,32,35,38,41,44,47]
Grundlagen der Programmierung 2 (1.C)
- 9 -
Auswertungsreihenfolge, Definitionseinsetzung
Auswertung von
f s1 . . . sn
wenn Muster verwendet wurden:
Vor Definitionseinsetzung
diejenigen Argumente auswerten,
die für die Fallunterscheidung benötigt werden.
Aber nur soviel wie nötig
Zuordnung: Mustervariablen zu Ausdruck
analog wie Zuordnung: formale Parameter zu Argumenten.
Z.B. Muster (x:xs) und Argument (s :t) ergibt [s/x, t/xs]
Grundlagen der Programmierung 2 (1.C)
- 10 -
Iterative Prozesse mit Listenargumenten
Bei Verwendung von Listenargumenten:
Die folgenden Begriffe sind unverändert:
linear rekursiv,
end-rekursiv,
Baum-rekursiv
verschachtelt Baum-rekursiv
iterativ muss neu definiert werden.
Grundlagen der Programmierung 2 (1.C)
- 11 -
Iterativer Auswertungsprozess zu f
Ein iterativer Auswertungsprozess liegt vor, wenn
(f a1 . . . an)
→
(3)
(f a1
(3)
→
. . . an )
(j)
und alle ai
(f a01 . . . a0n)
→
sind
......
(2)
→
(f a1
→
(f a1
(2)
. . . an )
(m)
(m)
. . . an
)
→ ...
Basiswerte oder
komplett ausgewertete, endliche Listen
Grundlagen der Programmierung 2 (1.C)
- 12 -
iterative Version fiter von f
fiter ist iterative Version von f
Wenn:
f und fiter das gleiche berechnen
und fiter einen iterativen Prozess erzeugt
für alle Basiswerte und
alle komplett ausgewerteten endlichen Listen als Eingaben
Grundlagen der Programmierung 2 (1.C)
- 13 -
Listen: Auswertung
Listenargumente nennt man:
einfach ausgewertet:
wenn Listen-Fallunterscheidung möglich ist,
d.h. [] oder : ist Top-Konstruktor des Arguments
Grundlagen der Programmierung 2 (1.C)
- 14 -
Beispiel: iterative Version von lengthr:
length_lin xs
= length_linr 0 xs
length_linr s []
= s
length_linr s (x:xs) = (length_linr (s+1) xs)
lengthr []
= 0
lengthr (x:xs) = 1 + lengthr xs
Grundlagen der Programmierung 2 (1.C)
- 15 -
Beispiel: iterativer Prozess
Beachte: applikative Reihenfolge der Auswertung
length_lin (9:(8:(7:(6:...(1:[])))))
length_linr 0
(9:(8:(7:(6:...(1:[])))))
length_linr 1
(8:(7:(6:...(1:[]))))
length_linr 2
(7:(6:...(1:[])))
length_linr 3
(6:...(1:[]))
..........
Grundlagen der Programmierung 2 (1.C)
- 16 -
Allgemeine Funktionen auf Listen
Allgemeine Funktionen (Methoden): foldl und foldr
Die 3 Argumente sind:
•
•
•
eine zweistellige Operation,
ein Anfangselement (Einheitselement) und
die Liste.
foldl ⊗ e [a1, . . . , an] entspricht ((. . . ((e ⊗ a1) ⊗ a2) . . . ) ⊗ an).
foldr ⊗ e [a1, . . . , an] entspricht a1 ⊗ (a2 ⊗ (. . . (an ⊗ e)))
Grundlagen der Programmierung 2 (1.C)
- 17 -
Definitionen der fold-Funktionen
foldl (Linksfaltung)
foldr (Rechtsfaltung)
foldl
:: (a -> b -> a) -> a -> [b] -> a
foldl f z []
= z
foldl f z (x:xs) = foldl f (f z x) xs
foldr
:: (a -> b -> b) -> b -> [a] -> b
foldr f z []
= z
foldr f z (x:xs) = f x (foldr f z xs)
Grundlagen der Programmierung 2 (1.C)
- 18 -
Fold-Verwendungen
Summe bzw. Produkt einer Liste von Zahlen:
sum xs
= foldl (+) 0 xs
produkt xs = foldl (*) 1 xs
concat xs = foldr (++) [] xs
foldl (+) 0 [1,2,3,4]
foldr (++) [] [[0],[2,3],[5]]
≡
≡
((((0+1)+2)+3)+4)
[0] ++ ([2,3] ++ ([5] ++ []))
Je nach Operator is foldl, oder foldr besser geeignet.
Grundlagen der Programmierung 2 (1.C)
- 19 -
Lokale Funktionsdefinitionen, anonyme Funktionen, Lambda-Ausdrücke
Kann Funktionsnamen ersetzen
Lambda-Ausdruck
\x1 . . . xn -> hAusdrucki
Die Notation \x -> ist Ersatz für die Church-Notation: λx.
Beispiel
quadrat =
\x -> x*x
Lokale Funktionsdefinition:
Anonyme Funktion
Lambda-Ausdruck an der Stelle von f
Lambda-Ausdruck hat keine Namen
Äquivalent sind:
\x1 -> (\x2 -> ... (\xn -> t) ...)
Grundlagen der Programmierung 2 (1.C)
und
\x1 x2 ... xn -> t.
- 20 -
let und lokale Bindungen
let {x1 = s1; . . . ; xn = sn} in t
{x1 = s1; . . . ; xn = sn}
ist eine lokale Umgebung
die Variablen xi können in t vorkommen
mit der Bedeutung: Wert von si
”
t
der eigentliche Ausdruck
In Haskell: rekursives let. D.h. xi kann in jedem sj vorkommen
Beachte im ghci-Interpreter: Spezielle Verwendung des let
Grundlagen der Programmierung 2 (1.C)
- 21 -
Erweiterungen des let
Funktionen sind definierbar direkt in einem rekursiven let:
let {f x1 . . . xn = s; . . .} in t
ist das gleiche wie:
let {f = \x1 . . . xn -> s; . . .} in t
Grundlagen der Programmierung 2 (1.C)
- 22 -
Reduktionen von let-Ausdrücken
nicht-rekursives let:
let {x1 = s1; . . . ; xn = sn} in t
t[s1/x1, . . . , sn/xn
mit Sharing-Markierungen
Wie man ein rekursives let weiter-reduzieren kann:
let {x1 = s1; . . . ; xn = sn} in t
let {x1 = s1σ; . . . ; xn = snσ} in tσ
mit σ = [s1/x1, . . . , sn/xn]
Grundlagen der Programmierung 2 (1.C)
- 23 -
Freie und Gebundene Variablen, Gültigkeitsbereiche
Um Definitionen von lokalen Namen korrekt zu handhaben braucht
man neue Begriffe:
Gültigkeitsbereich
einer Variablen x
freie Variablen
eines Ausdrucks
gebundene Variablen
eines Ausdrucks
Text-Fragment(e) des Programms in
dem dieses x gemeint ist.
Variablen, deren Bedeutung außerhalb
des Ausdrucks festgelegt wird.
Variablen, deren Bedeutung innerhalb
des Ausdrucks festgelegt wird.
Problem: Variablen können mit gleichem Namen, aber verschiedener
Bedeutung in einem Ausdruck vorkommen:
Lösung:
Exakte Festlegung der Gültigkeitsbereiche
für jedes syntaktische Konstrukt
Umbenennen von gebundenen Variablennamen, falls nötig
Grundlagen der Programmierung 2 (1.C)
- 24 -
Beispiel
\x-> x*x
Gültigkeitsbereich von x: der Ausdruck x*x
die Variable x ist gebunden von \x
x*x
in diesem Ausdruck ist x frei
Grundlagen der Programmierung 2 (1.C)
- 25 -
Definition von FV
FV: ergibt Menge von Variablen-Namen.
•
•
•
•
•
•
F V (x) := {x} , wenn x ein Variablenname ist
F V ((s t)) := F V (s) ∪ F V (t)
F V (if t1 then t2 else t3) := F V (t1) ∪ F V (t2) ∪ F V (t3)
F V (\x1 . . . xn -> t) := F V (t) \ {x1, . . . , xn}
F V (let x1 = s1, . . . , xn = sn in t)
:= (F V (t) ∪ F V (s1) ∪ . . . ∪ F V (sn)) \ {x1, . . . , xn}
F V (let f x1 . . . xn = s in t)
:= F V (let f = \x1 . . . xn -> s in t)
Grundlagen der Programmierung 2 (1.C)
- 26 -
Beispiel: freie Variablen
F V (\x -> (f x y))
Grundlagen der Programmierung 2 (1.C)
=
=
=
=
F V (f x y ) \ {x}
...
{x, f, y} \ {x}
{f, y}
- 27 -
Gebundene Variablen GV (t)
Entsprechend der F V -Definition:
•
•
•
•
•
•
GV (x) := ∅
GV ((s t)) := GV (s) ∪ GV (t)
GV (if t1 then t2 else t3) := GV (t1) ∪ GV (t2) ∪ GV (t3)
GV (\x1 . . . xn -> t) := GV (t) ∪ {x1, . . . , xn}
GV (let x1 = s1, . . . , xn = sn in t)
:= (GV (t) ∪ GV (s1) ∪ . . . ∪ GV (sn) ∪ {x1, . . . , xn}})
GV (let f x1 . . . xn = s in t)
:= GV (let f = \x1 . . . xn -> s in t)
= {f, x1, . . . , xn} ∪ GV (s) ∪ GV (t)
Grundlagen der Programmierung 2 (1.C)
- 28 -
Beispiel : Berechnung von gebundenen Variablen
GV(\x ->
(f x y))
Grundlagen der Programmierung 2 (1.C)
=
=
=
=
GV (f x y) ∪ {x}
...
∅ ∪ {x}
{x}
- 29 -
Lexikalischer Gültigkeitsbereich einer Variablen
•
let x = s
•
\x1 . . . xn -> t
in t
Grundlagen der Programmierung 2 (1.C)
die Vorkommen der freien Variablen x in s, t
werden gebunden.
s, t ist der Gültigkeitsbereich der Variablen x
die freien Variablen x1, . . . , xn in t werden gebunden.
t ist der Gültigkeitsbereich der Variablen
x1 , . . . , x n .
- 30 -
Beispiel
Ausdruck t = \x -> (x (\x -> x*x))
x ist in t gebunden, aber in zwei Bindungsbereichen:
\x -> (x (\x -> x*x))
In (x (\x -> x*x)) kommt x frei und gebunden vor.
Umbenennen des gebundenen x in y ergibt:
(x (\y -> y*y))
Grundlagen der Programmierung 2 (1.C)
- 31 -
Beispiele
Zwei Bindungsbereiche für x in einem let-Ausdruck:
let x = 10 in (let x = 100 in (x+x)) + x
Umbenennung ergibt:
let x1 = 10 in (let x2 = 100 in (x2+x2)) + x1
Dieser Term wertet zu 210 aus.
Grundlagen der Programmierung 2 (1.C)
- 32 -
Beispiele
Der Ausdruck
let x = (x*x) in (x+x)
führt zu Nichtterminierung.
Grundlagen der Programmierung 2 (1.C)
- 33 -
Beispiel: Reihenfolgenunabhängigkeit der Bindungen
let
y = 20*z
x = 10+y
z = 15
in x
Wertet aus zu : 310.
Grundlagen der Programmierung 2 (1.C)
- 34 -
Beispiel geschachtelte Bindungsbereiche
let {x = 1;y = 2}
in (let {y = 2; z = 4}
in (let z = 5
in (x+y+z)))
x = 1; y = 2
y = 2; z = 4
z=5
(x+y+z)
Grundlagen der Programmierung 2 (1.C)
- 35 -
Programm als let
Ein Programm
mit den Definitionen
fi := ei | i = 1, . . . , n
und dem auszuwertenden Ausdruck main
kann als großes“ let betrachtet werden:
”
let {f1 := e1; . . . ; fn := en} in main
Grundlagen der Programmierung 2 (1.C)
- 36 -
Optimierung mittels let
Vermeidung redundanter Auswertungen mit let
f (x, y) := x(1 + xy)2 + y(1 − y) + (1 + xy)(1 − y)
optimierbar durch Vermeidung von Doppelauswertungen:
Der zugehörige Ausdruck ist:
let a
= 1 + x*y
b
= 1 - y
in
x*a*a + y*b + a*b
Grundlagen der Programmierung 2 (1.C)
- 37 -
Allgemeine Methoden:
Funktionen als Argumente
Funktionen höherer Ordnung
Beispiele für (arithmetische) Aufgabenstellungen:
Nullstellenbestimmung,
Integrieren,
Differenzieren,
Ermitteln von Maxima, Minima von Funktionen . . .
Grundlagen der Programmierung 2 (1.C)
- 38 -
Nullstellenbestimmung einer stetigen Funktion
mit Intervallhalbierung
Sei f stetig und f (a) < 0 < f (b), m = (a + b)/2
f
a
(a+b)/2
b
• wenn f (m) > 0, dann Nullstelle in [a, m].
• wenn f (m) < 0, dann Nullstelle in [m, b].
Grundlagen der Programmierung 2 (1.C)
- 39 -
Nullstellenbestimmung: Programm (1)
Parameter:
•
•
•
•
Name der arithmetischen (Haskell-) Funktion
Intervall-Anfang
Intervall-Ende
Genauigkeit der Nullstelle (absolut).
suche_nullstelle::
(Double->Double) -> Double
-> Double
-> Double -> Double
suche_nullstelle f a b genau =
... (siehe Programmfile)
Grundlagen der Programmierung 2 (1.C)
- 40 -
Nullstellenbestimmung: Programm (3)
*Main> suche_nullstelle cos 0 3 0.000000000000001
1.5707963267948966
*Main> 1.5707963267948966/pi
0.5
*Main> pi/2
1.5707963267948966
*Main>
Grundlagen der Programmierung 2 (1.C)
- 41 -
Intervallhalbierungsmethode: Komplexität
maximale Anzahl der Schritte: dlog2(L/G)e,
wobei
L
G
Länge des Intervalls
Genauigkeit
Zeitbedarf:
Platzbedarf:
O(log(L/G))
O(1)
Grundlagen der Programmierung 2 (1.C)
- 42 -
Funktionen als Ergebnis
Beispiel: Komposition von Funktionen:
komp::(a -> b) -> (c -> a) -> c -> b
komp f g x = f (g x)
*Main> suche_nullstelle (sin ‘komp‘ quadrat) 1 4 0.00000001
1.772453852929175
(sin ‘komp‘ quadrat) entspricht sin(x2)
und quadrat ‘komp‘ sin entspricht (sin(x))2.
Grundlagen der Programmierung 2 (1.C)
- 43 -
Typ der Komposition
Erklärung zum Typ von komp, wobei {a,b,c} Typvariablen sind
Ausdruck: f1 ‘komp‘ f2 bzw. f1 . f2
(a->b) -> (c->a) -> c->b
(a->b)
(c->a)
c
b
Typ von komp
Typ von f1
Typ von f2
Typ des Arguments x
der Komposition f1 . f2
Typ des Resultats
der Komposition f1(f2 x)
f1 ‘komp‘ f2:: c -> b.
Grundlagen der Programmierung 2 (1.C)
- 44 -
Beispiel: näherungsweises Differenzieren
x
Df (x) :=
x+∆x
f (x + dx) − f (x)
dx
ableitung f dx =
\x -> ((f(x+dx)) - (f x)) / dx
Resultat: Funktion, die die Ableitung f 0 annähert
*Main> ((ableitung (\x -> x^3) 0.00001) 5)
75.00014999664018
---- korrekter Wert: 3*5^2 = 75
Grundlagen der Programmierung 2 (1.C)
- 45 -
Variante der Newtonschen Methode zur Bestimmung der Nullstellen
y2
Vorgehen:
y1
Ersetze Schätzwert y1 durch
f (y1)
verbesserten Schätzwert y2 = y1 −
.
Df (y1)
Grundlagen der Programmierung 2 (1.C)
- 46 -
Variante der Newtonschen Methode zur Bestimmung der Nullstellen (2)
newton_nst :: (Double -> Double) -> Double -> Double
newton_nst f y =
if (abs (f y)) < 0.0000000001
then y
else newton_nst f (newton_nst_verbessern y f)
newton_nst_verbessern y f = y - (f y) / (ableitung f
0.00001 y)
Beispiel: Nullstelle der Funktion x2 − x mit Startwert 4.
*Main> newton_nst (\x -> x^2-x) 4
1.0000000000001112
Grundlagen der Programmierung 2 (1.C)
- 47 -
Datentypen in Haskell
Basisdatentypen
•
•
•
•
•
•
Ganze Zahlen (Int)
Unbeschränkte ganze Zahlen (Integer).
Rationale Zahlen.
Komplexe Zahlen (im Haskell-Module Complex).
Gleitkommazahlen (Gleitpunktzahlen) (Float). z.B. 1.234 e-40
Zeichen, Character. i.a. ASCII-Zeichen zu 1 Byte bzw. Unicode
Grundlagen der Programmierung 2 (1.C)
- 48 -
Zusammengesetzte Daten-Objekte
Paar:
Beispiele
(x, y)
(1, 2)
(1, "hallo")
(1,(2,"hallo"))
Grundlagen der Programmierung 2 (1.C)
- 49 -
Anwendungs-Beispiel: Rationale Zahlen
Repräsentation als Paar: (Zähler, Nenner)
Beachte: in Haskell vordefiniert
x
in Haskell als
x%y gedruckt.
y
Beispiele:
Prelude> (3%4)*(4%5)
3 % 5
Prelude> 1%2+2%3
7 % 6
Datenkonversionen:
Grundlagen der Programmierung 2 (1.C)
z.B. toRational, truncate.
- 50 -
n-Tupel von Objekten
Als Verallgemeinerung von Paaren
(t1, . . . , tn)
ist n-Tupel von t1, . . . , tn
Beispiele
(1,2,3,True)
(1,(2,True),3)
("hallo",False)
(fakultaet 100,\x-> x)
Grundlagen der Programmierung 2 (1.C)
- 51 -
Zusammengesetzte Objekte: Datentypen
Für Datentypen benötigt man:
Datenkonstruktor(en)
Datenselektor(en)
Beispiel
Paarkonstruktor
Paarselektoren
s, t −→ (s, t)
fst, snd
Eigenschaften:
fst(s, t) = s und
snd(s, t) = t.
Grundlagen der Programmierung 2 (1.C)
- 52 -
Beispiel n-Tupel
n-Tupelkonstruktor
t1, . . . , tn −→ (t1, . . . , tn)
Tupelselektoren
n Selektoren: pro Stelle ein Selektor
n-Tupel haben einen impliziten Konstruktor:
(., . . . , .)
| {z }
n
Grundlagen der Programmierung 2 (1.C)
- 53 -
Definition der Selektoren
Muster (pattern) statt Selektoren.
Muster sind syntaktisch dort erlaubt, wo formale Parameter (Variablen)
neu eingeführt werden:
•
•
•
in Funktionsdefinitionen,
in Lambda-Ausdrücken und
in let-Ausdrücken.
Beispiel-Definitionen von Selektoren mittels Muster
fst (x,y) = x
snd (x,y) = y
selektiere_erstes_von_3 (x1,x2,x3) = x1
selektiere_zweites_von_3 (x1,x2,x3) = x2
selektiere_drittes_von_3 (x1,x2,x3) = x3
Grundlagen der Programmierung 2 (1.C)
- 54 -
Beispiel: Typen von Selektoren, Konstruktoren,
Tupeln
(1, 1)
::
(Integer, Integer)
(1, (2, True))
::
(Integer, (Integer, Bool))
(., . . . , .)
::
α1 → α2 → . . . → αn → (α1, α2, . . . , αn)
::
(α1, α2, α3) → α3
| {z }
n
selektiere_drittes_von_3
Grundlagen der Programmierung 2 (1.C)
- 55 -
Benutzerdefinierte Konstruktoren
In Haskell mittels data-Anweisung
Beispiel
data Punkt
= Punktkonstruktor Double Double
data Strecke
= Streckenkonstruktor Punkt Punkt
data Viertupel a b c d = Viertupelkons a b c d
Grundlagen der Programmierung 2 (1.C)
- 56 -
Muster (pattern)
Nutzen der Muster:
Gleichzeitiges und tiefes Selektieren
Ersatz für Selektoren
Syntax der Muster:
hMusteri ::= hVariablei | (hMusteri)
| hKonstruktor(n)i hMusteri . . . hMusteri
|
{z
n
}
| (hMusteri, . . . , hMusteri)
Kontextbedingung: in einem Muster keine Variable doppelt
Grundlagen der Programmierung 2 (1.C)
- 57 -
Auswertung unter Benutzung von Mustern
Mustervergleich:
Anpassen des Objekts an das Muster
gleichzeitige Selektion mittels impliziter let-Bindungen
I.a. vorher Auswertung des Objekts erforderlich
Beispiele
(x,y,(u,v)) anpassen an: (1,2,(3,4))
ergibt: let {x = 1;y = 2;u = 3;v = 4}
in ...
(x,y,(u,v)) anpassen an: (1,2,True)
ergibt: Fehler. Kann nicht vorkommen wegen Typcheck.
(x,y,u) anpassen an: (1,2,(4,5))
ergibt: let {x = 1; y = 2;u = (4,5)}
Grundlagen der Programmierung 2 (1.C)
in ...
- 58 -
Auswertung unter Benutzung von Mustern (2)
Beispiele
(x,y) anpassen an: (1,fakt 100)
ergibt: {let {x = 1; y = fakt 100} in ...
(x,y) anpassen an: (fst (1,2), snd (fakt 100,fakt 200))
ergibt :
let {x = fst (1,2); y = snd (fakt 100, fakt 200)} in ...
Grundlagen der Programmierung 2 (1.C)
- 59 -
Benutzerdefinierte Typnamen mit Parametern
Beispiel Punkt, Strecke, Polygonzug
data
data
data
data
Punkt a
Strecke a
Vektor a
Polygon a
=
=
=
=
Punkt a a
Strecke (Punkt a) (Punkt a)
Vektor a a
Polygon [Punkt a]
Typ und Konstruktor können gleiche Namen haben.
Der Parameter a kann jeder Typ sein: z.B.:
Float,
Int, aber auch [[(Int, Char)]]
Grundlagen der Programmierung 2 (1.C)
- 60 -
Funktionen auf Punkt, Strecke, Polygonzug
addiereVektoren::Num a => Vektor a -> Vektor a -> Vektor a
addiereVektoren (Vektor a1 a2) (Vektor b1 b2) =
Vektor (a1 + b1) (a2 + b2)
streckenLaenge (Strecke (Punkt a1 a2) (Punkt b1 b2)) =
sqrt (fromInteger ((quadrat (a1 - b1))
+ (quadrat (a2-b2))))
Grundlagen der Programmierung 2 (1.C)
- 61 -
Summentypen und Fallunterscheidung
Summentyp: diese haben mehr als einen Konstruktor
Beispiele: Bool mit True False
data Wahrheitswerte = Wahr | Falsch
Aufzählungstyp:
data Farben = Rot | Gruen | Blau | Weiss | Schwarz
data Kontostand = Dm (Integer) | Euro (Integer) | Dollar (Integer)
| SFranken (Integer)
Grundlagen der Programmierung 2 (1.C)
- 62 -
Funktionsdefinition mit mehreren Mustern:
Beispiele:
und1
und1
und1
und1
Wahr Falsch
Wahr Wahr
Falsch Falsch
Falsch Wahr
=
=
=
=
Falsch
Wahr
Falsch
Falsch
oder
und2
und2
Wahr x
Falsch x
= x
= Falsch
Wahr x
Falsch _
= x
= Falsch
oder
und3
und3
Grundlagen der Programmierung 2 (1.C)
--
Joker, Wildcard
- 63 -
Fallunterscheidung mit case
Syntax:
case hAusdrucki of {h Musteri -> hAusdrucki; . . . ;hMusteri -> hAusdrucki}
Einschränkung:
Kontextbedingung:
nur einfache Muster: K x1 . . . xn
die Muster müssen vom Typ her passen.
Beispiel:
und4
x y
= case x of True -> y; False -> False
Grundlagen der Programmierung 2 (1.C)
- 64 -
case: Gültigkeitsbereich, FV und GV
F V (case s of
(c1 x11 . . . x1n1 → t1); . . . ;
(ck xk1 . . . xknk → tk ))
=
F V (s) ∪ F V (t1) \ {x11, . . . x1n1 } . . .
∪ F V (tk ) \ {xk1, . . . xknk }
GV(.) entsprechend
Grundlagen der Programmierung 2 (1.C)
- 65 -
case: Gültigkeitsbereich, Beispiel
F V (case x of True -> y; False -> False)
=
{x,y}
F V (case x of (Punkt u v) -> u)
=
{x }
GV (case x of (Punkt u v) -> u)
=
{u,v}
Grundlagen der Programmierung 2 (1.C)
- 66 -
Herunterladen