fachen. So erlaubt Ha zuführen, die die Konstruktion diesem Grund

Werbung
feld
rund
es sich, weitere
ktion
Abstraktion
Abstraktion
Abstraktion
die
dielohnt
Konstruktion
und
dieNotationen
Verarbeitung
von Abstraktion Abstraktion Abstraktion Abstra
chen.
So
erlaubt
Haskell
z.B.
die
Notation
Folgen:
Folgen:�������
�������
�������Liste
Listebis
dereinschließlich
positiven Zahlen,
Zahlen,���
���
der
positiven
Zahlen
��
��,
,
����
der
ungeraden,
positiven
Zahlen,
ungeraden,
positiven
Zahlen
bis���������
einschliefl
lich
sind
jeweils
vom
Typ
���������
���������.
.
Die
untere
GrenzeDie
können
durch beliebige
Ausdr¸cke
werden.
Schrittweite
ergibt
sich
als Differenz
d
zweiten
Folgenglieds.
Um
Funktionen
defi
nieren,
haben
wir
bis
dato
rekursive
erwendet.Manchmal
können
listenverarbeitende
nfacher
und
lesbarer
mit
Listenbeschreibungen
�������und
���������ergibt
sich
daraus, einfach,
dafl hier da
dieSequen
Listen
werden.
Schauen
wir
uns
ein
paar
Beispiele
an: sind.
Sequenzen
Dieseauf
Instanz
istsich
besonders
rsten
hundert
Quadratzahlen
erh‰lt
man
mit
ihre
Repr‰sentation
Listen
eineindeutig
entsprechen.
Aus
diesem
Grund
lohnt
es sich,
weitere
Notationen
Algorithmen
und
Datenstrukturen
Isind
Algorithme
�������������������������������������
‰ndertsich
im
n‰chsten
Beispiel.Bin‰rb‰ume
eine
att
einzuführen,
die die
Konstruktion
und
die
Verarbeitung
von
strahieren
wir vonwir
einer
speziellen
Funktion
und
Repr‰sentation
von
Sequenzen:
Die
Verkettung
���wird
durc
Listenvereinfachen.
So
erlaubt
Haskell
z.B.
die
Notation
n
Liste,
erhalten
die
Funktion
���
���:
:
:��������
��������
implementiert
und
erfolgt (im
Unterschied
zu ���auf
Listen)
in
arithmetischer
Folgen:
Folgen:�������
�������
�������Liste
Liste
dereinschließlich
Zahlen,
Zahlen,���
���
���������
���������Somit
Somit ist ���������������������
Zeit..Andererseits
erreichen
wirImplementierung
dies
aufpositiven
Kosten
l‰ngerer
Laufz
�������Liste
�������
Liste
der
positiven
Zahlen
bis
��
��,
,
����
����
����.
.
Listenbeschreibungen
ermˆglichenoft
eine
���und
��.
Die
folgende
liegt
nahe:
���
������
������Liste
Liste
der
ungeraden,
positiven
Zahlen,
���������
rze Formulierung von Programmen:
Die
vorde
������������������������������������������������
����Liste
����
Liste
der ungeraden, positiven Zahlen bis einschliefllich
lernen
wirBeherrschung
gleichzeitig eine
neue Programmiertechnik
kenne
eine
gute
vorausgesetzt
uns
viel
Arbeit
erspare
In
Abschnitt
6.3.1
werden
wir sehen,
dafl die Sortierfunktion
Kapitel
4 Listen
fast
beliebiger
Typen
sortieren
können
ohne
groß
anstrengen
müssen.
Abhängig
vom
Typ
der
zu
sortieren
wird
automatisch
die entsprechende
Vergleichsfunktion
verd
Keine
Automatik
ohne
Nachteile,Betrachten
denn
nichtwir
immer
leistet
Voreinstellung
das
Gewünschte.
den
Datenty
���������������������������������������������
���������������������������������������������
���������������������������������������������
�������Da
lexikographisch
verglichen
wird,
werden
Elemen
�������zuerst
nachdem
Geschlecht,
dann
nach
dem
Vo
Typ
dem
Nachnamen
und
dem
Geburtsdatumangeordnet.
Selbst
wir
diezeigen
Vergleichsoperation
selbst
defiexibel:
nieren Wie
könnten
in Abs
6.3.2
wir wie,
bleiben
wir unfl
können
nic
aufsteigend
nach
dem
Nachnamen
und
ein
anderes
Mal
abst
nach
dem
Alter
zu sortieren.
Die Lösung für����zum
dieses Problem
i
Parame
einfach:
Wir
machen
diekönnen
Ordnungsrelation
Sortierfunktionen;
dann
wir
für
jede
Anwendung
ein
schneiderteOrdnungsrelation
angeben. Hier ist die Verallgem
von
�����:������������������������������������
���������������������������������������������
���������������������������������������������
�����������������������������������������Die
ur
Funktion
������erhalten
wir,
wenn
wir
f¸r
den
Parameter
wi
vordefi
nierte Ordnungsrelation
einsetzen:
�����sortieren
wir absteigend.
Listen
von������������;
Personen
lassen si
������������
vielen
unterschiedlichen
Kriterien
sortieren:
���������������������������������������������
���������������������������������������������
���������������������������������������������
���������������������������������Die
Definition
d
������������������wirft
eine
interessante
Frage
auf:Wie
zwei
Personen mit
demsich
gleichen
Geburtsdatum
angeordnet?
durchEinfügen
verhält
erfreulich:
Die relative
Anordnun
Personen
mit
dem
gleichenGeburtsdatum
wird
nicht
verände
��und
��zwei
Personen,
die
am
gleichen
Taggeboren
sind, s
���������������������������������������������
���������Sind
die
Personen
bereits
nach
dem
Nachnamen
so
bleibt
diese Anordnung
jegenauer
Geburtsdatum
erhalten.
Es loh
das
Phänomen
noch
einmal
zu
betrachten.
Bisher
si
davon
ausgegangen, daß eine
totale �Ordnung
definiert;
insb
muß
antisymmetrischsein:
����������
����.
Lassen
wir
wie
ou
Eigenschaft
fallen,
habenwir
nur
noch
eine
Präordnung
vor
Sortieralgorithmen
funktionieren
weiterhinì,nur
die Spezifik
Kapitel
4 ist
unter
diesen
abgeschwächten
Voraussetzungen
eindeutig,
da
es
mehrere
Permutationen
einer
Liste
geben ka
�
aufsteigend
geordnet
sind:
Die
Reihenfolge
von
Elementen
Prof.
Dr.
Robert
Giegerich
Prof.
Dr.
Robert
Giegeric
������
�
���ist
eben
nicht
festgelegt.
Verändert
ein
Sortierlagori
Wir der
hab
Reihenfolge
Elemente nicht,soEigenschaft
heißt er stabil.
dafl
Stabilitätdieser
eine wünschenswerte
ist. Von
�������nicht
stabil.
eingeführten
Sortieralgorithmen
ist
nur
��
läßt
sich durch
eine welche?
kleine Änderung
in der
stabilisieren.
Durch
Wir
wollen
die Hilfsfunktion
Verwendung
von
als
Parametern
noch
an
einem
weiteren
Beispiel
studieren,
d
�������������aus
Abschnitt
5.6
such
Suche.
Die
Funktion
in
einem
geordneten Feld.Vergleichsoperation
In Analogie zu den Sortierfunktio
wir
die
zugrundeliegende
zum Paramete
Aber
es
geht
noch
sehr
viel
allgemeiner:
Betrachten
wir die F
nition
von
�������������genauer:
Die
Vergleichsoperatio
����������������verwendet;
wird
nur
in dem
Ausdruck
Aufruf
ändert
sich
jedoch
lediglich
Von
daher liegt es die
nah
die
Binäre
Suche
mit
einer
Funktion�.zu
parametrisieren,
ein
Element
von
���������abbildet.
Daß
wir
in
einem
Feld
nunmehr
in
den
Hintergrund.Indem
wir
das
Suchintervall
üb
beseitigen
wir
die erfolgreich,
Abhängigkeit
ganz.wir
Noch
eine
letzte
Ände
��in
der
Form
����
wir
bei
der
Suche
geben
anderenfalls wird ��������zurückgegeben. ������������
���������������������������������������������
���������������������������������������������
Universität
Bielefeld Universität Bielefeld Universität Bielefeld
���������������������������������������������
���������������������������������������������
��������Die
Funktion
���������������implementiert
ÑSpielì:
Der Rechner
fordert
die Benutzerin
auf,
sich eine
Zad
��und
��auszudenken.
Der
Rechner
rät:
Ist
die
gesuchte
Zahl
Benutzerin
sagt, ob
die Zahl gefunden
wurde,
obdie
sieLösung
kleiner f
ist.
Nach
���������
�
���Schritten
weifl
der
Rechner
Antworten nicht gemogelt
wurde.
Im Programm
entspricht
d
����derBenutzerin:
Ist ��die
ausgedachte
Zahl,
so
beschrei
������������������ihr
Verhalten.
Liegt
��im
Intervall
�
ergibt
�������������������������gerade
������.
Was
es
eigentlich,
daß bei den
Antworten
gemogelt
wird?
Anders
WelcheAnforderungen
mufl
����erfüllen,
damit
die
Binäre
S
vernünftig
arbeitet?
Nun
wir
erwarten,
daß
es
höchstens
ein
gibt
mit ����������,
f¸r alle ������muß�����������gelten,
��entsprechend
����������.
Die �Funktion
����unterteilt����f
maximal
in
drei
Bereiche:
�����������
������������������������
��������Umfafl
t der
mittlere
Bereich
mehr
als ein Element,
f
die
Binäre
Suche
auch.
In
diesem
Fall
wird
irgendein
Elemen
mittleren
Drittel
zur¸ckgegeben. Formal mufl ����lediglich
a
sein: ������
������������mit
Verallgemeiner
Suche,
so daß
sie gerade das������������.
mittlere Drittel als
Intervall best
WS 2004/2005 WS 2004/2005 WS 2004/2005 WS 2
Sortierfunktionen?
Alle
Sortierfunktionen
sw
�����ab,
also klären
Vergleichsoperation
Typ.
Dazu
fragen
wir
sehrprinzipiell,
was
sic
läßt?Abs
Zahlen
und
Zeichen,
klar;
tion Abstraktionvergleichen
Abstraktion
wenn
wir
wissen,
wie
man
die
Komponent
Auch
Listen lassen
sich vergleichen,
wenn w
Listenelemente
vergleichen
kˆnnen:������
��������������������������������
����������Paare
Listen werden
hier
angeordnet.
Lexikasund
verwenden
die gleiche
kommt
vor
Beginn,
aber
nach
Anfall.
Auf
fa
läßtsich
eine
entsprechende
Ordnung
defi
n
eine
einzige
Ausnahme:
Funktionen.
Vielle
nicht
auf die
miteinander
In
diesem
FallIdee,
sollteFunktionen
man
sich vor
Augen f¸h
Korrektheitsbeweise
oft
nichts
anderes
machen.
Nachdem
die Korrektheit
von ���
ren Iwir
Algorithmen
u
�����gezeigt
war,
wußten
���������
stelle
sich
vor,
die
Gleichheit
von
Funktione
Rechnennachgewiesen
werden:
Wir hätten
�����zu
zeig
begnügt,
die
Korrektheit
von
Ausdruck ���������������in
denanRechn
Leidereine
Illusion,
wir
stoßen
hier
die
G
Mechanisierbarkeit:
Die
Gleichheit
von
Funktionen
ist formal unentscheidbar.
Wir
damit,
dies
festzustellen
und
verweisen
aufb
Literatur
zurTheoretischen
Informatik..Was
������
für
den Typ der
Sortierfunktionen?
allgemein,wir
müssen
die
Belegungen
der T
einschränken:
���������������������
�,
auf
denen
Vergleichsopera
für
alle
Typen
sind,
istein
�����������ein
Typ vonder
�����.
���ist
sogenannter
�������,
die A
��einschränkt.
Dabei ist ����e
Typvariable
Relation
auf
Typen,
eine
sogenannte
Typkla
durch
folgende
Regeln beschreiben läßt (w
Auswahl
auf):����������������������
�����������������
�������Lies
�����
���.
Wir
haben
oben
Instanz der Typklasse
����jeweils
defi
niert
wird.
In
Abhängigkei
������auf
die entsprechende
Vergle
greift
dies geschieht
automatisch
ohne unser
Zut
Nachtrag Listenbeschreibungen
divisors’ :: (Integral a) => a -> [a]
divisors’ n = [d | d <- [1..n], n ‘mod‘ d == 0]
primes’ :: (Integral a) => [a]
primes’ = [n | n <- [2..], divisors’ n == [1,n]]
Algorithmen und Datenstrukturen I
1
Nachtrag Listenbeschreibungen
divisors’ :: (Integral a) => a -> [a]
divisors’ n = [d | d <- [1..n], n ‘mod‘ d == 0]
primes’ :: (Integral a) => [a]
primes’ = [n | n <- [2..], divisors’ n == [1,n]]
sieve :: (Integral a) => [a] -> [a]
sieve (a:x) = a:sieve [n | n <- x, n ‘mod‘ a /= 0]
primes’’ :: (Integral a) => [a]
primes’’ = sieve [2..]
Algorithmen und Datenstrukturen I
1
Noch ein winziger Nachtrag
concat’ xs = [a | x <- xs, a <- x]
Algorithmen und Datenstrukturen I
2
8-Damen-Problem
4
Q
3
Q
[2,4,1,3]
2 Q
1
Q
1
Algorithmen und Datenstrukturen I
2
3
4
3
8-Damen-Problem
4
Q
3
Q
[2,4,1,3]
2 Q
1
Q
1
Algorithmen und Datenstrukturen I
2
3
4
4 −3 −2 −1 0
4 5 6 7 8
3 −2 −1
0
1
3 4 5 6 7
2 −1
0
1
2
2 3 4 5 6
1
0
1
2
3
1 2 3 4 5
1
2
3
4
1 2
3
4
3
type Board = [Integer]
queens :: Integer -> [Board]
queens n = place 1 [1..n] [] []
Algorithmen und Datenstrukturen I
4
place :: Integer -> [Integer] -> [Integer] -> [Integer] -> [Board]
place c [] ud dd = [[]]
place c rs ud dd = [q:qs | q <- rs,
let uq = q - c,
let dq = q + c,
uq ‘notElem‘ ud,
dq ‘notElem‘ dd,
qs <- place (c+1) (delete q rs) (uq:ud) (dq:dd)]
delete q (x:xs) | q == x
= xs
| otherwise = x:delete q xs
Algorithmen und Datenstrukturen I
5
Semantik von Listenbeschreibungen
Algorithmen und Datenstrukturen I
[ e | p <- l ]
=
map (\p -> e) l
[ e | b ]
=
if b then [e] else []
[ e | let ds ]
=
let ds in [e]
[ e | q1 , q2 ]
=
concat [ [ e | q2 ] | q1 ]
6
Funktionen als Parameter
data Person
= Person Sex FirstName LastName Date
deriving (Eq,Ord)
data Date
= Date Int Int Int deriving (Eq,Ord)
data Sex
= Female | Male
deriving (Eq,Ord)
type FirstName = String
type LastName = String
Algorithmen und Datenstrukturen I
7
isortBy :: (a -> a -> Bool) -> [a] -> [a]
isortBy (<=) = isort
where
isort []
= []
isort (a:x)
= insert a (isort x)
insert a []
= [a]
insert a x@(b:y)
| a <= b
= a:x
| otherwise = b:insert a y
Algorithmen und Datenstrukturen I
8
isortBy :: (a -> a -> Bool) -> [a] -> [a]
isortBy (<=) = isort
where
isort []
= []
isort (a:x)
= insert a (isort x)
insert a []
= [a]
insert a x@(b:y)
| a <= b
= a:x
| otherwise = b:insert a y
sortByLastName = isortBy (\p q -> components p <= components q)
where components (Person s f l d) = (l,f,d)
sortByDateOfBirth = isortBy (\p q -> dateOfBirth p <= dateOfBirth q)
where dateOfBirth (Person _ _ _ d) = d
Algorithmen und Datenstrukturen I
8
Binäre Suche 2
binarySearch :: (Ord b, Integral a, Ix a) => Array a b -> b -> Bool
binarySearch a e = within (bounds a)
where within (l,r) = l <= r
&& let m = (l + r) ‘div‘ 2
in case compare e (a!m) of
LT -> within (l, m-1)
EQ -> True
GT -> within (m+1, r)
Algorithmen und Datenstrukturen I
9
binarySearchBy’ :: (Integral a) => (a -> Ordering) -> (a,a) -> Bool
binarySearchBy’ cmp = within
where within (l,r) = if l > r then False
else let m = (l+r) ‘div‘ 2
in case cmp m of
LT -> within (l, m-1)
EQ -> True
GT -> within (m+1, r)
Algorithmen und Datenstrukturen I
10
binarySearchBy :: (Integral a) => (a -> Ordering) -> (a,a) -> Maybe a
binarySearchBy cmp = within
where within (l,r) = if l > r then Nothing
else let m = (l+r) ‘div‘ 2
in case cmp m of
LT -> within (l, m-1)
EQ -> Just m
GT -> within (m+1, r)
Algorithmen und Datenstrukturen I
11
binarySearchBy :: (Integral a) => (a -> Ordering) -> (a,a) -> Maybe a
binarySearchBy cmp = within
where within (l,r) = if l > r then Nothing
else let m = (l+r) ‘div‘ 2
in case cmp m of
LT -> within (l, m-1)
EQ -> Just m
GT -> within (m+1, r)
binSearch a e = case r of Nothing -> False; Just _ -> True
where r = binarySearchBy (\i -> compare e (a!i)) (bounds a)
Algorithmen und Datenstrukturen I
11
Wörterbuch
englishGerman :: Array Int (String, String)
englishGerman = listArray (1,2) [("daffodil", "Narzisse"),
("dandelion","Loewenzahn")]
Algorithmen und Datenstrukturen I
12
Wörterbuch
englishGerman :: Array Int (String, String)
englishGerman = listArray (1,2) [("daffodil", "Narzisse"),
("dandelion","Loewenzahn")]
german :: [Char] -> Maybe [Char]
german x = case r of Nothing -> Nothing
Just m -> Just (snd (englishGerman!m))
where r = binarySearchBy (\i -> compare x (fst (englishGerman!i)))
(bounds englishGerman)
Algorithmen und Datenstrukturen I
12
Offene Suche
openbinSearchBy :: (Integral a) => (a -> Ordering) -> a -> Maybe a
openbinSearchBy cmp l = lessThan l
where lessThan r = case cmp r of
LT -> binarySearchBy cmp (l,r)
EQ -> Just r
GT -> lessThan (2*r)
Algorithmen und Datenstrukturen I
13
Rekursionsschemata
Strukturelle Rekursion auf Listen:
Rekursionsbasis ([]) Das Problem wird für die leere Liste [] gelöst.
Rekursionsschritt (a:x) Um das Problem für die Liste a:x zu lösen, wird nach dem
gleichen Verfahren, d.h. rekursiv, zunächst eine Lösung für x bestimmt, die
anschließend zu einer Lösung für a:x erweitert wird.
Algorithmen und Datenstrukturen I
14
Vom Kochrezept zum Programm
structuralRecursionOnLists :: solution
-> (a -> [a] -> solution -> solution)
-> [a] -> solution
structuralRecursionOnLists base extend = rec
where rec []
= base
rec (a:x) = extend a x (rec x)
Algorithmen und Datenstrukturen I
-- base
-- extend
15
Insertionsort mit sROL
isort’ :: (Ord a) => [a] -> [a]
isort’ = structuralRecursionOnLists
[]
(\a _ s -> insert’’ a s)
insert’’ :: (Ord a) => a -> [a] -> [a]
insert’’ a = structuralRecursionOnLists
[a]
(\b x s -> if a <= b then a:b:x else b:s)
Algorithmen und Datenstrukturen I
16
Permutationen
perms [2,6,7] == [[2,6,7],[6,2,7],[6,7,2],[2,7,6],[7,2,6],[7,6,2]]
perms
[6,7] == [[6,7],[7,6]]
Algorithmen und Datenstrukturen I
17
Permutationen
perms [2,6,7] == [[2,6,7],[6,2,7],[6,7,2],[2,7,6],[7,2,6],[7,6,2]]
perms
[6,7] == [[6,7],[7,6]]
perms :: [a] -> [[a]]
perms []
= [[]]
perms (a:x) = [z | y <- perms x, z <- insertions a y]
insertions :: a -> [a] -> [[a]]
insertions a []
= [[a]]
insertions a x@(b:y) = (a:x):[b:z | z <- insertions a y]
Algorithmen und Datenstrukturen I
17
Eine Variante der sort-Spezifikation
sort :: (Ord a) => [a] -> [a]
sort x = head [s | s <- perms x, ordered s]
Algorithmen und Datenstrukturen I
18
Divide and Conquer
Ist das Problem einfach, wird es mit ad-hoc Methoden gelöst. Anderenfalls
wird es in einfachere Teilprobleme aufgeteilt, diese werden nach dem
gleichen Prinzip gelöst und anschließend zu einer Gesamtlösung
zusammengefügt.
Algorithmen und Datenstrukturen I
19
Divide and Conquer
Ist das Problem einfach, wird es mit ad-hoc Methoden gelöst. Anderenfalls
wird es in einfachere Teilprobleme aufgeteilt, diese werden nach dem
gleichen Prinzip gelöst und anschließend zu einer Gesamtlösung
zusammengefügt.
divideAndConquer :: (problem -> Bool)
--> (problem -> solution)
--> (problem -> [problem])
--> ([solution] -> solution)
--> problem -> solution
divideAndConquer easy solve divide conquer = rec
where rec x = if easy x then solve x
else conquer [rec y | y
Algorithmen und Datenstrukturen I
easy
solve
divide
conquer
<- divide x]
19
Mergesort mit dAC
msort’’ :: (Ord a) => [a] -> [a]
msort’’ = divideAndConquer
(\x -> drop 1 x == [])
(\x -> x)
(\x -> let k = length x ‘div‘ 2 in [take k x, drop k x])
(\[s,t] -> merge s t)
Algorithmen und Datenstrukturen I
20
Quicksort mit dAC
qsort :: (Ord a) => [a] -> [a]
qsort = divideAndConquer
(\x -> drop 1 x == [])
(\x -> x)
(\(a:x) -> [[ b | b <- x, b < a],[a],[b | b <- x, b >= a]])
(\[x,y,z] -> x++y++z)
Algorithmen und Datenstrukturen I
21
foldr und Kolleginnen
sum’’ :: (Num a) => [a] -> a
sum’’ []
= 0
sum’’ (a:x) = a + sum’’ x
or’’ :: [Bool] -> Bool
or’’ []
= False
or’’ (a:x) = a || or’’ x
Algorithmen und Datenstrukturen I
22
foldr und Kolleginnen
sum’’ :: (Num a) => [a] -> a
sum’’ []
= 0
sum’’ (a:x) = a + sum’’ x
or’’ :: [Bool] -> Bool
or’’ []
= False
or’’ (a:x) = a || or’’ x
foldr’ :: (a -> solution -> solution) -> solution -> [a] -> solution
foldr’ (*) e = f
where f []
= e
f (a:x) = a * f x
Algorithmen und Datenstrukturen I
22
sum’
product’
and’
or’
=
=
=
=
foldr
foldr
foldr
foldr
(+) 0
(*) 1
(&&) True
(||) False
(:) -> (*)
[] -> e
a1 :(a2 :· · ·:(an−1 :(an :[]))· · ·) -> a1 *(a2 *· · ·:(an−1 *(an :e))· · ·)
Algorithmen und Datenstrukturen I
23
Noch ein paar Beispiele
isort
length
x ++ y
reverse
concat
=
=
=
=
=
foldr
foldr
foldr
foldr
foldr
Algorithmen und Datenstrukturen I
insert []
(\n _ -> n + 1) 0
(:) y x
(\a x -> x ++ [a]) []
(++) []
24
Was macht die folgende Funktion?
mystery x = foldr (\a -> foldr (<->) [a]) [] x
where a <-> (b:x) = if a <= b then a:b:x else b:a:x
Algorithmen und Datenstrukturen I
25
foldr und foldl
*
/ \
a1 *
/ \
foldr (*) e
a2 .. <-----------\
*
/ \
an e
Algorithmen und Datenstrukturen I
:
/ \
a1
:
/ \
foldl (*) e
a2 .. ------------>
\
:
/ \
an []
*
/ \
*
an
/
..
/
*
/ \
e
a1
26
foldr und foldl
*
/ \
a1 *
/ \
foldr (*) e
a2 .. <-----------\
*
/ \
an e
:
/ \
a1
:
/ \
foldl (*) e
a2 .. ------------>
\
:
/ \
an []
foldr (*) e (reverse x)
=
*
/ \
*
an
/
..
/
*
/ \
e
a1
foldl (flip (*)) e x,
mit flip (*) = \a b -> b * a.
Algorithmen und Datenstrukturen I
26
foldl
foldl’’ :: (solution -> a -> solution) -> solution -> [a] -> solution
foldl’’ (*) e x = f x e
where f []
e = e
f (a:x) e = f x (e*a)
Algorithmen und Datenstrukturen I
27
reverse’’’’ = foldl (flip (:)) []
sum’’’
= foldl (+) 0
or’’’
= foldl (||) False
concat’’’ = foldl (++) []
Algorithmen und Datenstrukturen I
28
Speicher- und Zeitbedarf sum
sum’’ [1..9]
sum’’’ [1..9]
⇒
f [1..9]
⇒ f’ [1..9] 0
⇒
1 + f [2..9]
⇒ f’ [2..9] 1
⇒
1 + (2 + f [3..9])
⇒ f’ [3..9] 3
...
...
⇒
1 + (2 + ... + (9 + f []))
⇒ f’ [] 45
⇒
1 + (2 + ... + (9 + 0))
⇒ 45
⇒
45
Algorithmen und Datenstrukturen I
29
Speicher- und Zeitbedarf or
or’’ [False,True,False]
or’’’ [False,True,False]
⇒ f [False,True,False]
⇒ f’ [False,True,False] False
⇒ False || f [True,False]
⇒ f’ [True,False] (False || False)
⇒ f [True,False]
⇒ f’ [True,False] False
⇒ True || f [False]
⇒ f’ [False] (True || False)
⇒ True
⇒ f’ [False] True
⇒ f’ [] (False || True)
⇒ f’ [] True
⇒ True
Algorithmen und Datenstrukturen I
30
foldr1 und foldl1
foldr1 :: (a -> a -> a) -> [a] -> a
foldl1 :: (a -> a -> a) -> [a] -> a
foldr1 (*) = f
where f [a] = a
f (a:b:xs) = a * f (b:xs)
foldl1 (*) (x:xs) = foldl (*) x xs
Algorithmen und Datenstrukturen I
31
foldr1 und foldl1
foldr1 :: (a -> a -> a) -> [a] -> a
foldl1 :: (a -> a -> a) -> [a] -> a
foldr1 (*) = f
where f [a] = a
f (a:b:xs) = a * f (b:xs)
foldl1 (*) (x:xs) = foldl (*) x xs
righty, lefty :: [a] -> Tree a
righty = foldr1 Br . map Leaf
lefty = foldl1 Br . map Leaf
Algorithmen und Datenstrukturen I
31
foldm
:
*
/ \
/
\
a1
:
*
*
/ \
foldm (*) e
/
\
/
\
a2 .. ------------>
..
..
..
..
\
/
\
/
\
:
*
* ... *
*
/ \
/ \
/ \
/ \
/ \
an []
a1 a2 ai-1 ai ai+1 ai+2 an-1 an
Algorithmen und Datenstrukturen I
32
foldm :: (a
foldm (*) e
foldm (*) e
where f
-> a -> a) -> a -> [a] -> a
[] = e
x = fst (f (length x) x)
n x = if n == 1 then (head x, tail
else let m
= n
(a,y) = f
(b,z) = f
in (a*b,z)
Algorithmen und Datenstrukturen I
x)
‘div‘ 2
m
x
(n-m) y
33
foldm :: (a
foldm (*) e
foldm (*) e
where f
-> a -> a) -> a -> [a] -> a
[] = e
x = fst (f (length x) x)
n x = if n == 1 then (head x, tail
else let m
= n
(a,y) = f
(b,z) = f
in (a*b,z)
foldm1 (*) = foldm (*) (error "foldm1 []")
Algorithmen und Datenstrukturen I
x)
‘div‘ 2
m
x
(n-m) y
33
mergeList :: (Ord a) => [[a]] -> [a]
mergeList = foldm merge []
balanced :: [a] -> Tree a
balanced = foldm1 Br . map Leaf
msortBy, smsortBy :: (a -> a -> Bool) -> [a] -> [a]
msortBy (<=) = foldm (mergeBy (<=)) [] . map (\a -> [a])
smsortBy (<=) = foldm (mergeBy (<=)) [] . runsBy (<=)
Algorithmen und Datenstrukturen I
34
Fold auf Bäumen
foldTree :: (a -> b) -> (b -> b -> b) -> Tree a -> b
foldTree leaf br = f
where f (Leaf a) = leaf a
f (Br l r) = br (f l) (f r)
Algorithmen und Datenstrukturen I
35
Fold auf Bäumen
foldTree :: (a -> b) -> (b -> b -> b) -> Tree a -> b
foldTree leaf br = f
where f (Leaf a) = leaf a
f (Br l r) = br (f l) (f r)
size’
depth’
mergeTree’
mergeRuns’
=
=
=
=
foldTree
foldTree
foldTree
foldTree
Algorithmen und Datenstrukturen I
(\a -> 1) (+)
(\a -> 0) (\m n -> max m n + 1)
(\a -> [a]) merge
id merge
35
map und Kolleginnen
map :: (a -> b) -> [a] -> [b]
map f []
= []
map f (a:x) = f a:map f x
Algorithmen und Datenstrukturen I
36
Anwendung: Vektoren und Matrizen
type Vector a = [a]
type Matrix a = [Vector a]


3
2
8
17
0
1


[[3,8,0],[2,17,1]]
Algorithmen und Datenstrukturen I
37
(<*>):: (Num a) => a -> Vector a -> Vector a
k <*> x = map (\a -> k*a) x
Algorithmen und Datenstrukturen I
38
(<*>):: (Num a) => a -> Vector a -> Vector a
k <*> x = map (\a -> k*a) x
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith f (a:x) (b:y) = f a b:zipWith f x y
zipWith _ _
_
= []
Algorithmen und Datenstrukturen I
38
(<*>):: (Num a) => a -> Vector a -> Vector a
k <*> x = map (\a -> k*a) x
zipWith :: (a -> b -> c) -> [a] -> [b] -> [c]
zipWith f (a:x) (b:y) = f a b:zipWith f x y
zipWith _ _
_
= []
(<+>) :: (Num a) => Vector a -> Vector a -> Vector a
x <+> y = zipWith (+) x y
(<.>) :: (Num a) => Vector a -> Vector a -> a
x <.> y = sum (zipWith (*) x y)
Algorithmen und Datenstrukturen I
38
zip :: [a] -> [b] -> [(a,b)]
zip = zipWith (\a b -> (a,b))
Algorithmen und Datenstrukturen I
39
zip :: [a] -> [b] -> [(a,b)]
zip = zipWith (\a b -> (a,b))
k <*> x = [k*a | a <- x]
x <+> y = [a+b | (a,b) <- zip x y]
x <.> y = sum [a*b | (a,b) <- zip x y]
Algorithmen und Datenstrukturen I
39
(<++>) :: (Num a) => Matrix a -> Matrix a -> Matrix a
a <++> b = zipWith (<+>) a b
Algorithmen und Datenstrukturen I
40
(<++>) :: (Num a) => Matrix a -> Matrix a -> Matrix a
a <++> b = zipWith (<+>) a b
(<**>) :: (Num a) => Matrix a -> Matrix a -> Matrix a
m <**> n = [[x <.> y | y <- transpose’ n] | x <- m]
Algorithmen und Datenstrukturen I
40
Induktionsschritt transpose
a11
a12
···
a1n
a11
a12
a1n
a2n
a21
a22
a2n
a21
a22
a31
..
.
a32
..
.
a3n
..
.
a31
..
.
a32
..
.
am1
am2
amn
am1
am2
Algorithmen und Datenstrukturen I
···
···
a3n
..
.
amn
41
Induktionsschritt transpose
a11
a12
···
a1n
a11
a12
a1n
a2n
a21
a22
a2n
a21
a22
a31
..
.
a32
..
.
a3n
..
.
a31
..
.
a32
..
.
am1
am2
amn
am1
am2
···
···
a3n
..
.
amn
transpose’ :: Matrix a -> Matrix a
transpose’ = foldr (zipWith (:)) (repeat [])
Algorithmen und Datenstrukturen I
41
Typpolymorphismus und Typklassen
(++) :: [a] -> [a] -> [a]
"hello " ++ "world"
⇒
"hello world"
[19, 9] ++ [7]
⇒
[19, 9, 7]
["hello ","world"] ++ ["it’s","me"]
⇒
["hello ","world","it’s","me"]
Algorithmen und Datenstrukturen I
42
Ein paar polymorphe Funktionen ...
head
tail
leaves
build
map
::
::
::
::
::
[a] -> a
[a] -> [a]
Tree a -> [a]
[a] -> Tree a
(a -> b) -> ([a] -> [b])
Algorithmen und Datenstrukturen I
43
Vergleichsoperator (<=)
(a,b) <= (c,d) = a < c || a == c && b <= d
[]
<= x
= True
(a:x) <= []
= False
(a:x) <= (b:y) = a < b || a == b && x <= y
Algorithmen und Datenstrukturen I
44
Typklasse Ord
isort :: (Ord a) => [a] -> [a]
Algorithmen und Datenstrukturen I
45
Typklasse Ord
isort :: (Ord a) => [a] -> [a]
Ord Integer
Ord Char
Ord a ∧ Ord b ⇒ Ord (a, b)
Ord a ⇒ Ord [a]
Algorithmen und Datenstrukturen I
45
isort ["Beginn","Anfall","Anfang"]
⇒
["Anfall","Anfang","Beginn"]
isort [(3,1),(1,7),(1,3),(2,2)]
⇒
[(1,3),(1,7),(2,2),(3,1)]
Verschiedene (<=)!
Algorithmen und Datenstrukturen I
46
Die Typklasse Show
show :: (Show a) => a -> String
Algorithmen und Datenstrukturen I
show 123
⇒
"123"
show [1, 2, 3]
⇒
"[1, 2, 3]"
show "123"
⇒
"\"123\""
47
Eq und Ord
unique :: (Eq a) => [a] -> [a]
element :: (Eq a) => a -> [a] -> Bool
insert :: (Ord a) => a -> [a] -> [a]
merge :: (Ord a) => [a] -> [a] -> [a]
Algorithmen und Datenstrukturen I
48
data Ordering = LT | EQ | GT
compare :: (Ord a) => a -> a -> Ordering
uniqueInsert’ a []
= [a]
uniqueInsert’ a x@(b:y) = case
LT
EQ
GT
Algorithmen und Datenstrukturen I
compare a b of
-> a:x
-> x
-> b:uniqueInsert’ a y
49
Die Typklasse Num ((+), (-), (*))
size :: (Num n) => Tree a -> n
depth :: (Num n, Ord n) => Tree a -> n
Algorithmen und Datenstrukturen I
50
Integral und Fractional
power :: (Num a, Integral b) => a -> b -> a
power x n
| n == 0
= 1
| n ‘mod‘ 2 == 0 = y
| otherwise
= y*x
where y = power (x*x) (n ‘div‘ 2)
Algorithmen und Datenstrukturen I
51
Untertypklassen
Eq
Show
/
\
/
Ord
Num
\
/ \
Integral Fractional
Algorithmen und Datenstrukturen I
52
Beispiel rationale Zahlen, (==)
data Rat = Rat Int Int
Falsche Definition (Rat 67 18 /= Rat 8241 2214):
Rat x y == Rat x’ y’ =
x == x’ && y == y’
Richtige Definition:
Rat x y == Rat x’ y’ = x*y’ == x’*y
Algorithmen und Datenstrukturen I
53
class- und instance-Deklarationen (Eq und Ord)
class Eq a where
(==), (/=) :: a -> a -> Bool
x /= y = not (x == y)
instance Eq Rat where
Rat x y == Rat x’ y’ =
Algorithmen und Datenstrukturen I
x*y’ == x’*y
54
Rat mit smart-Konstruktor
rat :: Int -> Int -> Rat
rat x y = norm (x * signum y) (abs y)
where norm x y = let d = gcd x y in Rat (x ‘div‘ d) (y ‘div‘ d)
Algorithmen und Datenstrukturen I
55
Beispiel Binärbäume
instance (Eq
Leaf a
(Br l r)
_
a)
==
==
==
Algorithmen und Datenstrukturen I
=> Eq (Tree a) where
Leaf b
= a == b
Br l’ r’ = l == l’ && r == r’
_
= False
56
Beispiel Binärbäume
instance (Eq
Leaf a
(Br l r)
_
a)
==
==
==
=> Eq (Tree a) where
Leaf b
= a == b
Br l’ r’ = l == l’ && r == r’
_
= False
Allgemeine Form einer Instanzdeklaration:
instance (C1 β1 ,...,Cm βm ) => C(T α1 . . . αn ) mit
{β1 , . . . , βm } ⊆ {α1 , . . . , αn }.
Algorithmen und Datenstrukturen I
56
Ord als Untertypklasse von Eq
class (Eq a) => Ord a where
compare
:: a -> a -> Ordering
(<), (<=), (>=), (>) :: a -> a -> Bool
max, min
:: a -> a -> a
compare x y | x == y
= EQ
| x <= y
= LT
| otherwise = GT
x
x
x
x
<=
<
>=
>
y
y
y
y
=
=
=
=
compare
compare
compare
compare
Algorithmen und Datenstrukturen I
x
x
x
x
y
y
y
y
/=
==
/=
==
GT
LT
LT
GT
57
max x y |
|
min x y |
|
Algorithmen und Datenstrukturen I
x >= y
otherwise
x <= y
otherwise
=
=
=
=
x
y
x
y
58
instance Ord Rat where
Rat x y <= Rat x’ y’ = x*y’ <= x’*y
Algorithmen und Datenstrukturen I
59
instance Ord Rat where
Rat x y <= Rat x’ y’ = x*y’ <= x’*y
instance
Nil
Leaf
Leaf
Leaf
Br _
Br _
Br l
(Ord
<=
_ <=
a <=
_ <=
_ <=
_ <=
r <=
Algorithmen und Datenstrukturen I
a) => Ord (Tree a) where
t
= True
Nil
= False
Leaf b
= a <= b
Br _ _
= True
Nil
= False
Leaf _
= False
Br l’ r’ = l < l’ || l == l’ && r <= r’
59
Ausgabe eines Baums
showTree
showTree
showTree
showTree
:: Tree String -> String
Nil
= "Nil"
(Leaf a) = "Leaf " ++ a
(Br l r) = "Br " ++ showTree l ++ " " ++ showTree r
showTree (Br (Br (Leaf "a") (Leaf "b")) Nil)
=> "Br Br Leaf a Leaf b Nil"
Algorithmen und Datenstrukturen I
60
Ausgabe eines Baums
showTree
showTree
showTree
showTree
:: Tree String -> String
Nil
= "Nil"
(Leaf a) = "Leaf " ++ a
(Br l r) = "Br " ++ showTree l ++ " " ++ showTree r
showTree (Br (Br (Leaf "a") (Leaf "b")) Nil)
=> "Br Br Leaf a Leaf b Nil"
leaves
leaves
leaves
leaves
:: Tree a -> [a]
Nil
= []
(Leaf a) = [a]
(Br l r) = leaves l ++ leaves r
Algorithmen und Datenstrukturen I
60
foldTree :: (a -> b) -> (b -> b -> b) -> Tree a -> b
foldTree leaf br = f
where f (Leaf a) = leaf a
f (Br l r) = br (f l) (f r)
Algorithmen und Datenstrukturen I
61
foldTree :: (a -> b) -> (b -> b -> b) -> Tree a -> b
foldTree leaf br = f
where f (Leaf a) = leaf a
f (Br l r) = br (f l) (f r)
myFoldTree :: b -> (a -> b) -> (b -> b -> b) -> Tree a -> b
myFoldTree nil leaf br = f
where f Nil
= nil
f (Leaf a) = leaf a
f (Br l r) = br (f l) (f r)
Algorithmen und Datenstrukturen I
61
myShowTree
nil
=
leaf a =
br l r =
= myFoldTree nil leaf br where
"Nil"
"Leaf " ++ a
"Br " ++ l ++ " " ++ r
Algorithmen und Datenstrukturen I
62
myShowTree
nil
=
leaf a =
br l r =
showTree’
showTree’
showTree’
showTree’
= myFoldTree nil leaf br where
"Nil"
"Leaf " ++ a
"Br " ++ l ++ " " ++ r
:: Tree String -> String -> String
Nil s
= "Nil" ++ s
(Leaf a) s = "Leaf " ++ a ++ s
(Br l r) s = "Br " ++ showTree’ l (" " ++ showTree’ r s)
Algorithmen und Datenstrukturen I
62
showTree’’
showTree’’
showTree’’
showTree’’
:: Tree String -> ShowS
Nil
= showString "Nil"
(Leaf a) = showString "Leaf " . showString a
(Br l r) = showString "Br " . showTree’’ l . showChar ’ ’
. showTree’’ r
Algorithmen und Datenstrukturen I
63
showTree’’
showTree’’
showTree’’
showTree’’
:: Tree String -> ShowS
Nil
= showString "Nil"
(Leaf a) = showString "Leaf " . showString a
(Br l r) = showString "Br " . showTree’’ l . showChar ’ ’
. showTree’’ r
type ShowS =
String -> String
showChar :: Char -> ShowS
showChar = (:)
showString :: String -> ShowS
showString = (++)
Algorithmen und Datenstrukturen I
63
Die Typklasse Show
class Show a where
showsPrec :: Int -> a -> ShowS
showList :: [a] -> ShowS
showList []
= showString "[]"
showList (a:x) = showChar ’[’ . shows a . showRest x
where showRest []
= showChar ’]’
showRest (a:x) = showString ", " . shows a . showRest x
Algorithmen und Datenstrukturen I
64
shows :: (Show a) => a -> ShowS
shows = showsPrec 0
show :: (Show a) => a -> String
show x = shows x ""
showParen :: Bool -> ShowS -> ShowS
showParen b p = if b then showChar ’(’ . p . showChar ’)’ else p
Algorithmen und Datenstrukturen I
65
instance Show Rat where
showsPrec p (Rat x y) = showParen (p > 9)
(showString "Rat " . showsPrec 10 x
. showsPrec 10 y)
Algorithmen und Datenstrukturen I
66
instance Show Rat where
showsPrec p (Rat x y) = showParen (p > 9)
(showString "Rat " . showsPrec 10 x
. showsPrec 10 y)
instance Show Rat where
showsPrec p (Rat x y) = showParen (p > 9)
(showString "Rat " . showsPrec 10 x
. showChar ’ ’
. showsPrec 10 y)
Algorithmen und Datenstrukturen I
66
instance (Show a) => Show (Tree a) where
showsPrec p Nil
= showString "Nil"
showsPrec p (Leaf a) = showParen (p > 9)
(showString "Leaf " . showsPrec 10 a)
showsPrec p (Br l r) = showParen (p > 9)
(showString "Br " . showsPrec 10 l
. showChar ’ ’ . showsPrec 10 r )
Algorithmen und Datenstrukturen I
67
Die Typklasse Num
class (Eq a, Show
(+), (-), (*)
negate
abs, signum
fromInteger
a)
::
::
::
::
=> Num a where
a -> a -> a
a -> a
a -> a
Integer -> a
x-y = x + negate y
Algorithmen und Datenstrukturen I
68
instance Num Rat where
Rat x y + Rat x’ y’
Rat x y * Rat x’ y’
negate (Rat x y)
abs (Rat x y)
signum (Rat x y)
fromInteger x
fromInt x
Algorithmen und Datenstrukturen I
=
=
=
=
=
=
=
Rat
Rat
Rat
Rat
Rat
Rat
Rat
(x*y’ + x’*y) (y*y’)
(x*x’) (y*y’)
(negate x) y
(abs x) (abs y)
(signum (x*y)) 1
(fromInteger x) 1
(fromInt x) 1
-- Hugs-spezifisch
69
Herunterladen