Programmieren in Haskell

Werbung
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Programmieren in Haskell
WS 2013/2014
Robert Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
Universität Bielefeld
AG Praktische Informatik
8. Januar 2014
DatentypSpezifikationen
Themen-Vorschau
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Pattern Matching: as-Patterns und lazy Patterns
Client-Server-Programmierung
Abstrakte Datentypen
Module in Haskell
Holy Lists
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Pattern Matching in Haskell
Universität Bielefeld
Programmieren
in Haskell
Pattern matching (alias Mustervergleich) kennen wir bereits
Giegerich
aus Funktionsgleichungen
Pattern
Matching
aus case-Ausdrücken
Lazy patterns
Ein Pattern (Muster) ist ein Ausdruck bestehend aus
Variablen,
der anonymen Variablen _ (“Joker”)
Konstruktoren aller Datentypen
Zahlen, Characters
... also keine Funktionen, die nicht Konstruktoren sind
... und keine Variable mehrfach, ausgenommen _
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Ergonomie des Pattern Matching in Haskell
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern matching leistet zweierlei
1
2
3
Pattern
Matching
Fallunterscheidung in übersichtlicher Form
Lazy patterns
Nutzung der Reihenfolge bei überlappenden Mustern
Prüfungen,
Vorbereitung
Bindung von Muster-Variablen an Substrukturen des
geprüften Werts
Abstrakte
Datentypen
Haskell
Modules
leaves ( Leaf a ) = [ a ]
Datentypleaves ( Br ( Leaf a ) y ) = a : leaves y
Spezifikationen
leaves ( Br ( Br x y ) z ) = leaves ( Br x ( Br y z ))
As-Patterns
Manchmal will man Muster verwenden und einen Namen für
den (unzerlegten) Argumentwert haben
Universität Bielefeld
Programmieren
in Haskell
Giegerich
1
2
suffixes ( x : xs ) = ( x : xs ): suffixes xs
erzeugt eine überflüssige (:) Operation, vergeudet Zeit und
verschwendet Platz.
Besser mit as-pattern
suffixes z@(x:xs) = z: suffixes xs
Nun ist das schon vorhandene x:xs unter dem Namen z zu
haben.
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
As-Patterns
Manchmal will man Muster verwenden und einen Namen für
den (unzerlegten) Argumentwert haben
Universität Bielefeld
Programmieren
in Haskell
Giegerich
1
2
suffixes ( x : xs ) = ( x : xs ): suffixes xs
erzeugt eine überflüssige (:) Operation, vergeudet Zeit und
verschwendet Platz.
Besser mit as-pattern
suffixes z@(x:xs) = z: suffixes xs
Nun ist das schon vorhandene x:xs unter dem Namen z zu
haben.
Nebenbei: Welche Komplexität hat die Berechnung von
suffixes x?
Und welche die Ausgabe des Ergebnisses?
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Pattern Matching und Auswertungreihenfolge
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Vergleich eines Musters mit einem Wert erfordert,
Lazy patterns
dass der Wert ausgerechnet wird,
Prüfungen,
Vorbereitung
aber nur soweit es für den Vergleich nötig ist (Laziness)
Abstrakte
Datentypen
Verwendung von Mustern hat also Auswirkung auf die
Berechenungsreihenfolge
Haskell
Modules
DatentypSpezifikationen
Abweisbare und nicht abweisbare Muster
Universität Bielefeld
Programmieren
in Haskell
a.k.a. refutable versus irrefutable patterns
Ein Muster ohne Konstruktoren (also x, _ ) passt auf
jedem Wert und heißt unabweisbar
Ein Muster mit Konstruktoren heißt abweisbar
1
2
3
Ist eine Funktion mit unabweisbaren Mustern definiert, ist sie
immer ein Redex.
Beispiele:
square x = x * x
double f = f . f
five _ = 5
NB: Man kann alle Funktionen auf der linken Seite mit
unabweisbaren Mustern schreiben, wenn man stattdessen
case-Ausdrücke auf der rechten Seite verwendet.
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Pattern Matching und Terminierung (1)
Erinnerung: Die Auswertungsstrategie in einer funktionalen
Sprache hat keinen Einfluss auf den ggf. berechneten Wert,
wohl aber auf die Terminierung der Berechnung.
Ein Mustervergleich kann positive oder negativ ausgehen, oder
divergieren
Alle Muster in einer Gleichung werde top-down,
links-rechts verglichen
Geht ein Vergleich negativ aus, ist die aktuelle Gleichung
nicht anwendbar, und es wird die nachfolgende Gleichung
versucht
Ruft der Vergleich eine nicht-endende Berechnung hervor,
divergiert er und das Ergebnis der Gesamtrechnung ist
undefiniert.
Passen alle Muster einer Gleichung, wird sie angewendet
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Bottom
Universität Bielefeld
Programmieren
in Haskell
Giegerich
1
Hier eine Definition des “undefinierten” Werts
> bot = bot
bot, ausgesprochen “bottom” ist der gänzlich undefinierte
Wert. Seine Berechnung terminiert nicht, und produziert auch
keinen Konstruktor.
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Bottom
Universität Bielefeld
Programmieren
in Haskell
Giegerich
1
Hier eine Definition des “undefinierten” Werts
> bot = bot
bot, ausgesprochen “bottom” ist der gänzlich undefinierte
Wert. Seine Berechnung terminiert nicht, und produziert auch
keinen Konstruktor.
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
Was wäre ein teilweise undefinierter Wert?
DatentypSpezifikationen
Bottom
Universität Bielefeld
Programmieren
in Haskell
Giegerich
1
Hier eine Definition des “undefinierten” Werts
> bot = bot
bot, ausgesprochen “bottom” ist der gänzlich undefinierte
Wert. Seine Berechnung terminiert nicht, und produziert auch
keinen Konstruktor.
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
Was wäre ein teilweise undefinierter Wert?
Nebenbei: Welchen Typ hat bot?
DatentypSpezifikationen
Pattern Matching und Terminierung (2)
Universität Bielefeld
Programmieren
in Haskell
Giegerich
1
2
3
1
2
3
Vergleiche
take 0 _
= []
take _ []
= []
take n ( x : xs ) = x : take (n -1) xs
und mit vertauschten Zeilen
take ’ _ []
= []
take ’ 0 _
= []
take ’ n ( x : xs ) = x : take ’ (n -1) xs
Einen Unterschied gibt es nur, wenn eines der Argumente
undefiniert ist ...
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Unterschiedliches Terminierungsverhalten
Universität Bielefeld
Programmieren
in Haskell
Giegerich
1
2
take 0
take ’ 0
bot
bot
= = > []
= = > undefiniert
5
Lazy patterns
Prüfungen,
Vorbereitung
3
4
Pattern
Matching
take bot []
take ’ bot []
= = > undefiniert
= = > []
Abstrakte
Datentypen
Haskell
Modules
Der Haskell Prelude implementiert die Version take.
DatentypSpezifikationen
Lazy Patterns
Universität Bielefeld
Programmieren
in Haskell
a.k.a. Muster mit verzögertem Vergleich
Problem:
Man möchte eine Funktion mit einem Muster definieren
und zwar für ein Argument, das durch die Anwendung der
Funktion erst berechnet wird
Zwar steht fest, dass das Muster erfüllt sein wird, jedoch zum
Zeitpunkt der Funktionsaufrufs muss für den Mustervergleich
die gleiche Funktion wieder aufgerufen werden ...
Wo kommt so etwas überhaupt vor?
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Client-Server-Anwendungen
Client-Server-Anwendungen sind parallel laufende Programme,
die über Ströme kommunizieren
Nachrichten an einander – Requests und Responses –
werden wechselseitig erzeugt und gelesen
Sie werden in “Strömen” (streams) verwaltet.
Ströme sind in Haskell einfach lazy Listen,
in andern Sprachen weden sie als spezieller Datentyp zur
Verfügung gestellt.
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Zahlen raten als client-server Programm (1)
Ratespiel: Finde eine Zahl n aus dem Intervall [0..N] durch
Fragen der Art
”Ist n ≤ z?”
mit geschickt gewählten
Vergleichszahlen z.
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Zahlen raten als client-server Programm (1)
Ratespiel: Finde eine Zahl n aus dem Intervall [0..N] durch
Fragen der Art
”Ist n ≤ z?”
mit geschickt gewählten
Vergleichszahlen z.
Rollenverteilung:
Client: Erzeugt Fragen und merkt sich das Ergebnis.
Seine Strategie: Intervall-Halbierung; sie führt garantiert in
O(log(N)) Schritten zum Ziel.
Server: Kennt n und beantwortet Fragen ”Ist n ≤ z?” mit
True oder False.
Der Server antwortet wahrheitsgemäß. (In einer
interesssanteren Variante des Spiels darf er einmal lügen.)
Kommunikation zwischen Client und Server über zwei
Ströme: questions und answers.
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Zahlen raten als client-server Programm (2)
Eine Frage hat die Form (l,g,u) und bedeutet
ausführlich:
“Ich weiß dass n ∈ [l..u] und frage ob n ≤ g.”
g ist dabei die Intervallmitte, und wird, je nach Antwort,
für die nächste Frage ins linke oder rechte Halbintervall
verlegt.
Das Ende erkennt der Client daran, dass das Intervall sich
nicht mehr ändert.
1
2
3
4
5
>
>
>
>
>
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
minN = 0
DatentypSpezifikatiomaxN = 1024
nen
−− t a k e d i f f [ ] = [ ]
−− t a k e d i f f [ x ] = [ x ]
t a k e d i f f ( x : y : x s ) = x : i f y == x then [ ] e l s e t a k e d i f f ( y : x s )
takediff nimmt den Präfix einer Liste bis zur ersten
Wiederholung
Zahlen raten als client-server Programm (2)
Universität Bielefeld
Programmieren
in Haskell
Wir definieren die Prozesse ask und reply, die über die Listen
questions und answers kommunizieren.
Giegerich
Pattern
Matching
1
2
3
4
patterns
> guess n
= t a k e d i f f (map ( \ ( _ , g , _) −> g ) q u e s t i o n s )Lazywhere
Prüfungen,
>
answers
= reply questions
Vorbereitung
>
r e p l y ( ( _ , g , _ ) : q s ) = ( n <= g ) : r e p l y q s
Abstrakte
Datentypen
5
6
7
8
9
10
>
>
>
>
>
q u e s t i o n s = a s k i n i t i a l a n s w e r s where
Haskell
Modules
i n i t i a l = ( minN , (maxN + minN ) ‘ d i v ‘ 2 , maxN)
a s k ( l , g , u ) ( a : a s ) = ( l , g , u ) : a s k n e w g u e s s a s where
Datentypnewguess
= i f a then ( l ,
(l +
g ) ‘ d i vSpezifikatio‘ 2 , g)
nen
e l s e ( g +1, ( g+1 + u ) ‘ d i v ‘ 2 , u )
Zahlen raten als client-server Programm (2)
Universität Bielefeld
Programmieren
in Haskell
Wir definieren die Prozesse ask und reply, die über die Listen
questions und answers kommunizieren.
Giegerich
Pattern
Matching
1
2
3
4
patterns
> guess n
= t a k e d i f f (map ( \ ( _ , g , _) −> g ) q u e s t i o n s )Lazywhere
Prüfungen,
>
answers
= reply questions
Vorbereitung
>
r e p l y ( ( _ , g , _ ) : q s ) = ( n <= g ) : r e p l y q s
Abstrakte
Datentypen
5
6
7
8
9
10
>
>
>
>
>
q u e s t i o n s = a s k i n i t i a l a n s w e r s where
Haskell
Modules
i n i t i a l = ( minN , (maxN + minN ) ‘ d i v ‘ 2 , maxN)
a s k ( l , g , u ) ( a : a s ) = ( l , g , u ) : a s k n e w g u e s s a s where
Datentypnewguess
= i f a then ( l ,
(l +
g ) ‘ d i vSpezifikatio‘ 2 , g)
nen
e l s e ( g +1, ( g+1 + u ) ‘ d i v ‘ 2 , u )
Diese Version funktioniert nicht – warum?
Verklemmung!
Universität Bielefeld
Programmieren
in Haskell
Der Aufruf von ask (l,g,u) (a:as)
Giegerich
stellt eine Frage ((l,g,u)),
Pattern
Matching
die von reply beantwortet wird (a)
Lazy patterns
fragt jedoch in seinem rechten Muster bereits nach dieser
Antwort ((a:as)),
um aus ihr die nächste Frage (newguess) zu generieren
Das pattern matching beim Aufruf von ask kommt zu frueh:
es verlangt ein Ergbnis von reply,
bevor der gegebene Aufruf von ask das erste Element von
questions generiert hat.
reply seinerseits verlangt ein Ergebnis von ask ...
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Zahlen raten als client-server Programm (3)
Vermeidung des übereifrigen Musters:
1
2
3
Universität Bielefeld
Programmieren
in Haskell
Giegerich
>
>
answers
= reply questions
r e p l y ( (_, g ,_ ) : qs )
= ( n <= g ) : r e p l y q s
>
>
>
>
>
>
q u e s t i o n s = a s k i n i t i a l a n s w e r s where
Prüfungen,
i n i t i a l = ( minN , (maxN + minN ) ‘ d i v ‘ 2 , maxN)
Vorbereitung
a s k ( l , g , u ) a s = ( l , g , u ) : a s k n e w g u e s s ( t a i l a s ) where
Abstrakte
a
= head a s
Datentypen
newguess
= i f a then ( l ,
(l
+ g ) ‘ d i v ‘ 2 ,Haskell
g)
e l s e ( g +1, ( g+1 + u ) ‘ d i v ‘ 2 ,Modules
u)
Pattern
Matching
4
5
6
7
8
9
10
Lazy patterns
ask kann nun starten, ohne zuerst nach der Zerlegung der
answers-Liste as zu fragen.
Also kann die Frage ausgegeben und daraus die erste
Antwort erzeugt werden, bevor mit head as nach ihr
gefragt wird
DatentypSpezifikationen
Zahlen raten als client-server Programm (4)
Der gleiche Effekt mit lazy pattern ~(a:as)
O t h e r w i s e , t h e same a s s o l u t i o n ( 1 )
1
Universität Bielefeld
Programmieren
in Haskell
Giegerich
2
3
> guess ’ ’ n
= t a k e d i f f (map ( \ ( _ , g , _) −> g ) q u e s t i o n s )Pattern
where
Matching
4
5
6
answers
= reply questions
r e p l y ( ( _ , g , _ ) : q s ) = ( n <= g ) : r e p l y q s
>
>
>
>
>
Abstrakte
q u e s t i o n s = a s k i n i t i a l a n s w e r s where
Datentypen
i n i t i a l = ( minN , (maxN + minN ) ‘ d i v ‘ 2 , maxN)
Haskell
a s k ( l , g , u ) ~( a : a s ) = ( l , g , u ) : a s k n e w g u e s s a s where
Modules
newguess
= i f a then ( l ,
(l +
g ) ‘ d i vDatentyp‘ 2 , g)
e l s e ( g +1, ( g+1 + u ) ‘ d i vSpezifikatio‘ 2 , u)
7
8
9
10
11
12
Lazy patterns
>
>
Prüfungen,
Vorbereitung
nen
der lazy pattern ~(a:as) wird beim Aufruf als erfüllt
angenommen
erst wenn a oder as gebraucht wird, findet der Abgleich
statt.
Lazy Patterns
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Lazy patterns, ~(...)
sind unabweisbar.
Ihre Überprüfung findet nur statt, wenn eine Komponente
daraus gebraucht wird
Scheitert sie, bricht die Rechnung ab.
Eine weitere Mustergleichung nach einer Gleichung mit einem
lazy Pattern macht also keinen Sinn.
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Top level pattern binding: immer lazy
Universität Bielefeld
Programmieren
Werden Muster nicht auf Argumentposition, sondern in der
in Haskell
Definition von Konstanten benutzt, sind sie automatisch lazy:
Giegerich
fibp@(1:tfibp) = 1:1:[a+b | (a,b) <- zip fibp tfibp ]
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Top level pattern binding: immer lazy
Universität Bielefeld
Programmieren
Werden Muster nicht auf Argumentposition, sondern in der
in Haskell
Definition von Konstanten benutzt, sind sie automatisch lazy:
Giegerich
fibp@(1:tfibp) = 1:1:[a+b | (a,b) <- zip fibp tfibp ]
Hier haben wir einen as-Pattern, der eine konstante,
unendliche Liste definiert, ...
... die Liste der Fibonacci-Zahlen.
Das Muster bindet die Gesamtliste an den Namen fibp,
zugleich ihren tail an den Namen tfibp
die linke Seite fragt, ob die Liste nicht leer ist,
aber dank der laziness des Musters wird dies erst geprüft,
wenn tfibp rechts benutzt wird
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Top level pattern binding: immer lazy
Universität Bielefeld
Programmieren
Werden Muster nicht auf Argumentposition, sondern in der
in Haskell
Definition von Konstanten benutzt, sind sie automatisch lazy:
Giegerich
fibp@(1:tfibp) = 1:1:[a+b | (a,b) <- zip fibp tfibp ]
Hier haben wir einen as-Pattern, der eine konstante,
unendliche Liste definiert, ...
... die Liste der Fibonacci-Zahlen.
Das Muster bindet die Gesamtliste an den Namen fibp,
zugleich ihren tail an den Namen tfibp
die linke Seite fragt, ob die Liste nicht leer ist,
aber dank der laziness des Musters wird dies erst geprüft,
wenn tfibp rechts benutzt wird
Vergleiche:
let a@(1:as) = 1:[] in 2:a
let a@(0:as) = 1:[] in 2:a
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Infos und Tipps zu den Prüfungen
Universität Bielefeld
Programmieren
in Haskell
Die Veranstaltungen des Moduls “Algorithmen und
Datenstrukturen” werden gemeinsam in einer
Modulabschluss-Prüfung geprüft.
wissenschaftlicher Sinn einer Prüfung: Feststellen, ob
ausreichende Grundlagen für weiterführende
Veranstaltungen vorhanden sind.
wissenschaftlich unsinnig, aber systemimmanent:
Leistungsvergleich, Noten, peinliche Buchführung über den
Ausbildungsgang zum Ausweis von Unterschieden
Voraussetzung der Zulassung zur Prüfung sind 50% der Punkte
aus den Übungen zu A&D+Haskell.
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Mündliche Prüfung zum Modul A&D
Welche Veranstaltungen werden geprüft?
A&D Vorlesung
Programmieren in Haskell
A&D + Haskell Übung
Programmieren in der UNIX-Umgebung
Wer prüft?
Prüfer
Beisitzer
Wie lange?
20 Minuten
Wann?
siehe Termine
Was muss mitgebracht werden?
Personalausweis bzw. Pass
Studentenausweis
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Prüfungsziel
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Test, inwieweit Veranstaltungsinhalte verstanden werden und
angewendet werden können.
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Prüfungsziel
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Test, inwieweit Veranstaltungsinhalte verstanden werden und
angewendet werden können.
Pattern
Matching
Lazy patterns
Verschiedene Arten von Leistungen
Prüfungen,
Vorbereitung
Reproduktion
Abstrakte
Datentypen
Transfer (konkret)
Haskell
Modules
Transfer (abstrakt)
DatentypSpezifikationen
Prüfungsziel
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Test, inwieweit Veranstaltungsinhalte verstanden werden und
angewendet werden können.
Pattern
Matching
Lazy patterns
Verschiedene Arten von Leistungen
Prüfungen,
Vorbereitung
Reproduktion
Abstrakte
Datentypen
Transfer (konkret)
Haskell
Modules
Transfer (abstrakt)
Prüfen auf eine möglichst gute Note hin.
DatentypSpezifikationen
Termine
Universität Bielefeld
Programmieren
in Haskell
Robert Giegerich
2. und 4. Februar-Woche, und ggf. später
Alex Sczyrba
3. Februar-Woche, 3. März-Woche
Terminvereinbarung bei Stefanie Lanfermann (M3-127)
(Frau Lanfermann meldet die Prüfung im Dekanat an)
weitere Prüfer:
Prof. Dr. Stoye (mail an Heike Samuel)
Prof. Dr. Hammer (14.,17.,18.2.) (mail an Gisela
Weitekemper)
Prof. Dr. Nattkemper (mail an Heike Samuel)
Dr. Thies Pfeiffer (mail an Stefanie Lanfermann)
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Vorbereitung
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Materialien
Vorlesungsfolien
Übungsunterlagen
Skript
Prüfungsprotokolle, dabei jeweils beachten:
Motivation
Hintergrund
Übungsgruppen
Sprechstunden
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Ablauf
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Ausweiskontrolle
Prüfer stellt die Fragen
Beisitzer protkolliert hauptsächlich
Einstiegsfrage
nach ∼ 20 Minuten: Ende
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Student geht vor die Tür
Haskell
Modules
Prüfer und Beisitzer beraten sich kurz
DatentypSpezifikationen
Student wird wieder hereingebeten
Mitteilung der Note und Feedback
10 einfache Regeln zum Versemmeln einer Prüfung
(G.Sauthoff)
1
erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung
beginnen
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
10 einfache Regeln zum Versemmeln einer Prüfung
(G.Sauthoff)
1
2
erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung
beginnen
alleine Lernen, obwohl das eigentlich noch nie gut
geklappt hat
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
10 einfache Regeln zum Versemmeln einer Prüfung
(G.Sauthoff)
1
2
3
erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung
beginnen
alleine Lernen, obwohl das eigentlich noch nie gut
geklappt hat
bei der Vorbereitung das Skript ignorieren
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
10 einfache Regeln zum Versemmeln einer Prüfung
(G.Sauthoff)
1
2
3
4
erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung
beginnen
alleine Lernen, obwohl das eigentlich noch nie gut
geklappt hat
bei der Vorbereitung das Skript ignorieren
Verzicht auf eine aktive Bearbeitung der Übungen
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
10 einfache Regeln zum Versemmeln einer Prüfung
(G.Sauthoff)
1
2
3
4
5
erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung
beginnen
alleine Lernen, obwohl das eigentlich noch nie gut
geklappt hat
bei der Vorbereitung das Skript ignorieren
Verzicht auf eine aktive Bearbeitung der Übungen
strikt vermeiden, ein Haskell-Programm selbst zu schreiben
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
10 einfache Regeln zum Versemmeln einer Prüfung
(G.Sauthoff)
1
2
3
4
5
6
erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung
beginnen
alleine Lernen, obwohl das eigentlich noch nie gut
geklappt hat
bei der Vorbereitung das Skript ignorieren
Verzicht auf eine aktive Bearbeitung der Übungen
strikt vermeiden, ein Haskell-Programm selbst zu schreiben
Inhalte auswendig lernen
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
10 einfache Regeln zum Versemmeln einer Prüfung
(G.Sauthoff)
1
2
3
4
5
6
7
erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung
beginnen
alleine Lernen, obwohl das eigentlich noch nie gut
geklappt hat
bei der Vorbereitung das Skript ignorieren
Verzicht auf eine aktive Bearbeitung der Übungen
strikt vermeiden, ein Haskell-Programm selbst zu schreiben
Inhalte auswendig lernen
möglichst unausgeschlafen in die Prüfung kommen
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
10 einfache Regeln zum Versemmeln einer Prüfung
(G.Sauthoff)
1
2
3
4
5
6
7
8
erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung
beginnen
alleine Lernen, obwohl das eigentlich noch nie gut
geklappt hat
bei der Vorbereitung das Skript ignorieren
Verzicht auf eine aktive Bearbeitung der Übungen
strikt vermeiden, ein Haskell-Programm selbst zu schreiben
Inhalte auswendig lernen
möglichst unausgeschlafen in die Prüfung kommen
auf die Frage nach Unklarheiten vor dem Beginn der
Prüfung am besten sehr lang und breit erklären, wie
schlecht vorbereitet man doch ist
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
10 einfache Regeln zum Versemmeln einer Prüfung
(G.Sauthoff)
1
2
3
4
5
6
7
8
9
erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung
beginnen
alleine Lernen, obwohl das eigentlich noch nie gut
geklappt hat
bei der Vorbereitung das Skript ignorieren
Verzicht auf eine aktive Bearbeitung der Übungen
strikt vermeiden, ein Haskell-Programm selbst zu schreiben
Inhalte auswendig lernen
möglichst unausgeschlafen in die Prüfung kommen
auf die Frage nach Unklarheiten vor dem Beginn der
Prüfung am besten sehr lang und breit erklären, wie
schlecht vorbereitet man doch ist
kommunizieren, dass man die Begriffe in den
Veranstaltungstiteln nicht erklären kann
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
10 einfache Regeln zum Versemmeln einer Prüfung
(G.Sauthoff)
1
2
3
4
5
6
7
8
9
10
erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung
beginnen
alleine Lernen, obwohl das eigentlich noch nie gut
geklappt hat
bei der Vorbereitung das Skript ignorieren
Verzicht auf eine aktive Bearbeitung der Übungen
strikt vermeiden, ein Haskell-Programm selbst zu schreiben
Inhalte auswendig lernen
möglichst unausgeschlafen in die Prüfung kommen
auf die Frage nach Unklarheiten vor dem Beginn der
Prüfung am besten sehr lang und breit erklären, wie
schlecht vorbereitet man doch ist
kommunizieren, dass man die Begriffe in den
Veranstaltungstiteln nicht erklären kann
trotz Krankheit zur Prüfung erscheinen
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Weitere Angebote
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
ZSB bietet Workshops an
eher allgemeine Hinweise
vieles ist wahrscheinlich schon bekannt
eher sinnvoll bei extremer Prüfungsangst o.Ä.
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Abstrakte Datentypen
Universität Bielefeld
Programmieren
in Haskell
Giegerich
In der Software-Entwicklung unterscheidet zwei Arten von
Datentypen:
Pattern
Matching
Lazy patterns
konkrete Datentypen beziehen sich auf eine konkrete
Repräsentation in der verwendeten Programmiersprache.
Beispiele: Int, Char, Listen, Bäume; auch polymorphe
Datentypen sind konkret!
abstrakte Datentypen sind nicht an eine konkrete
Repräsentation gebunden.
Wie kann man dann überhaupt etwas definieren?
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Abstrakte Datentypen
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Ein abstrakter Datentyp (ADT) ist, unabhängig von einer
Programmiersprache,
eine (nicht weiter spezifizierte) Wertemenge
mit Operationen auf dieser Wertemenge,
die bestimmte Axiome (Gleichungen) erfüllen
die Menge der Operationen ist die Schnittstelle (API) nach
außen
konkrete Repräsentation der Daten in der Implementierung
ist nicht nach außen sichtbar (Kapselung)
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Warum?
Universität Bielefeld
Programmieren
in Haskell
Programmieren mit ADTs erhöht die Wiederverwendbarkeit von
Programmen
Beispiel: ADT Verzeichnis
Giegerich
Pattern
Matching
Lazy patterns
Operationen auf Verzeichnissen:
Prüfungen,
Vorbereitung
Erzeugen, Einfuegen, Loeschen, Sortieren, Bereinigen
Programmierer, die Verzeichnisse verwenden, kennen NUR
diese Operationen
Verzeichnisse können konkret Listen, Bäume, Arrays,...
sein, ggf. mit Zusatzoperationen
Die konkrete Implementierung kann geändert werden,
ohne dass andere Programme davon betroffen sind
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Abstrakte Datentypen
Universität Bielefeld
Programmieren
in Haskell
Abstrakte Datentypen spielen eine bedeutende Rolle in der
Software-Entwicklung
Alle modernen Programmiersprachen unterstützen ihre
Verwendung
Sie dienen der Spezifikation der nach außen sichtbaren
Operationen und Eigenschaften
Manchmal werden die Operationen mit Effizienzvorgaben
verknüpft
In Haskell werden abstrakte Datentypen durch Module
und durch Typklassen unterstützt.
In Java/C++ geschieht dies durch Klassen ud Interfaces
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Mini-ADT Llist
Universität Bielefeld
Programmieren
in Haskell
Wir spezifizieren einen ADT Llist a analog zu Listen, dessen
length-Funktion die Komplexität O(1) haben soll.
Operationen:
Giegerich
Pattern
Matching
Lazy patterns
empty :
→ Llist a
in O(1)
(1)
Prüfungen,
Vorbereitung
lcons :
a × Llista → Llist a
in O(1)
(2)
Abstrakte
Datentypen
lhead :
Llist a → a
in O(1)
(3)
Haskell
Modules
Llist a → Llist a
in O(1)
(4)
Llist a → Int
in O(1)
(5)
in O(n)
(6)
ltail :
llength :
lapp : Llist a × Llist a → Llist a
DatentypSpezifikationen
Eigenschaften
Universität Bielefeld
Programmieren
in Haskell
Eigenschaften der Operationen:
lhead(lcons(x , xs)) = x
ltail(lcons(x , xs)) = xs
llength(lcons(x , empty )) = 1
Giegerich
(7)
(8)
(9)
llength(lapp(xs, ys)) = llength(xs) + llength(ys)(10)
lapp(x , empty ) = x
und so weiter ...
Können wir das spontan implementieren?
(11)
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Module in Haskell
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Aus einigen Beispielen bekannt:
Modulname
Imports-Deklarationen
Definitionen des Moduls
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Module in Haskell
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Aus einigen Beispielen bekannt:
Modulname
Imports-Deklarationen
Definitionen des Moduls
1
2
3
4
5
> module Meinmodul
> where
> import Data . List
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
> splits n = [ splitAt k [1.. n ] | k <- [1.. n -1] ]
Modulaufbau — Was bisher verschwiegen wurde
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Ein Haskell-Modul ist eine Datei, welche wie folgt
eingeleitet wird:
module <Name> (<Exportliste>) where
Nur die Datentypen und Funktionen, die in
<Exportliste> angegeben werden, sind nach außen hin
sichtbar
Wenn <Exportliste> weggelassen wird, sind alle
Definitionen nach außen sichtbar.
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Exportieren von Datentypen
1
module Liste ( List ) where
Universität Bielefeld
Programmieren
in Haskell
Giegerich
2
3
4
data List a = Nil
| Cons a ( List a )
Pattern
Matching
Dies exportiert nur den Datentyp List, nicht aber die
Konstruktoren Nil und Cons. Diese können in dem
importierenden Modul nicht verwendet werden
Prüfungen,
Vorbereitung
module Liste ( List ( Nil , Cons )) where
exportiert auch die Konstruktoren
alternativ:
module Liste ( List (..)) where
exportiert alle Konstruktoren eines Datentyps
Lazy patterns
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
ADT-Beispiel: Holy Lists
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Anhängen eines Elements am Ende einer Liste erfordert O(n)
Schritte. “Holy Lists” erlauben diese Operation in O(1).
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
1
2
3
4
Abstrakte
Spezifikation:
Datentypen
> module Hlist ( l2h , h2l , lcons , rcons ) where
Haskell
> l2h ::
[a]
-> Hlist a -- in O ( n )Modules
> h2l ::
Hlist a
-> [ a ]
-- in O ( n )DatentypSpezifikatio> lcons :: a -> Hlist a -> Hlist a -- in O (1)nen
> rcons :: Hlist a -> a -> Hlist a -- in O (1)
Holy Lists
5
Stack
Queue
Set
Multi-Set
Holy Lists: Eigenschaften
Universität Bielefeld
Programmieren
in Haskell
Giegerich
1
2
Einige der erwarteten Eigenschaften:
l2h . h2l = id
( Konvertierung )
h2l . l2h = id
(
"
)
Lazy patterns
Prüfungen,
Vorbereitung
3
4
Pattern
Matching
reverse ( h2l ( rcons as a )) = a : h2l as
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Holy Lists: Eigenschaften
Universität Bielefeld
Programmieren
in Haskell
Giegerich
1
2
Einige der erwarteten Eigenschaften:
l2h . h2l = id
( Konvertierung )
h2l . l2h = id
(
"
)
Lazy patterns
Prüfungen,
Vorbereitung
3
4
Pattern
Matching
reverse ( h2l ( rcons as a )) = a : h2l as
Abstrakte
Datentypen
Haskell
Modules
Implementierung ???
Zum Nachdenken über die Feiertage!
Tipp: “holy” kommt von “hole” – Listen mit “Loch” am Ende
...
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Schöne Feiertage und Guten Rutsch
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
Dieser Foliensatz wird noch weiter ergänzt im neuen Jahr.
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
ADT Holy Lists
Universität Bielefeld
Programmieren
in Haskell
Giegerich
1
2
3
4
Pattern
type Hlist a
Matching
empty :: Hlist a
-- klassisch
Lazy patterns
cons
:: a -> Hlist a -> Hlist a
Prüfungen,
Vorbereitung
append :: Hlist a -> Hlist a -> Hlist a
Abstrakte
Datentypen
5
6
hcons
:: Hlist a -> a -> Hlist a
-- neu !!
l2h
h2l
:: [ a ] -> Hlist a
:: Hlist a -> [ a ]
-- Konversion
Spezifikatio-
Haskell
Modules
7
8
9
Datentypnen
Holy Lists
Stack
Queue
Set
Multi-Set
Axiome für ADT Holy Lists
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Forderungen an die Implementierung:
Alle Eigenschaften von (:), [], (++) sollen auch für
cons, empty, append gelten.
h2l . l2h == id
hcons h a == l2h (h2l h ++ [a])
Konvertierung (l2h l) und (h2l h) in O(n)
hcons h a in O(1)
Die letzte Anforderung ist die eigentliche Herausforderung!
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Lösungsvorschlag
Universität Bielefeld
Programmieren
in Haskell
Giegerich
1
2
Implementierung siehe Datei hlist.lhs
Pattern
Auszug:
Matching
Hlist - Listen mit effizientem Anfuegen vorneLazyund
h
patterns
Append - Funktion ebenfalls in O (1)
Prüfungen,
Vorbereitung
3
4
5
6
7
8
9
Specification
Abstrakte
Datentypen
Haskell
Modules
> module Hlist ( l2h , h2l , lcons , rcons ) where
> l2h ::
[a]
-> Hlist a -- in O ( n )DatentypSpezifikatio> h2l ::
Hlist a
-> [ a ]
-- in O ( n )nen
> lcons :: a -> Hlist a -> Hlist a -- in O (1)
uns so weiter ...
Holy Lists
Stack
Queue
Set
Multi-Set
ADT-Beispiel: Stack
Ein Stack (“Stapel” oder auch “Keller”) ist ein Datentyp, der
eine Menge von gleichartigen Elementen aufnehmen kann. Er
unterstützt fünf Operationen:
emptystack: Liefert einen Stack ohne Inhalt
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
stackEmpty s: Fragt ob ein Stack s leer ist
Prüfungen,
Vorbereitung
push x s: Legt ein neues Element x auf den Stack s
Abstrakte
Datentypen
pop s: Entfernt das oberste Element vom Stack
Haskell
Modules
top s: Liefert das oberste Element des Stacks s, ohne
dieses zu entfernen
DatentypSpezifikationen
Holy Lists
Last-In-First-Out (LIFO)-Strategie:
Das letzte Element, was auf den Stack gelegt wurde, ist das
erste, was wieder heruntergenommen wird.
Stack
Queue
Set
Multi-Set
Stack-Schnittstelle in Haskell
1
2
module Stack ( Stack , push , pop , top ,
emptyStack , stackEmpty ) where
3
4
5
6
7
8
emptyStack ::
stackEmpty ::
push :: a ->
pop :: Stack
top :: Stack
Stack a
Stack a -> Bool
Stack a -> Stack a
a -> Stack a
a -> a
emptyStack liefert einen neuen, leeren Stack
stackEmpty überprüft, ob der Stack leer ist
push legt ein Element auf den Stack
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
pop entfernt das oberste Element vom Stack
Set
Multi-Set
top liefert das oberste Element vom Stack
Stack-Implementierung (1)
Universität Bielefeld
Programmieren
1
2
> module S t a c k ( Stack , emptyStack , stackEmpty , pop , push ,in Haskell
top )
> data S t a c k a = St [ a ]
Giegerich
3
4
5
> emptyStack : : Stack a
> e m p t y S t a c k = St [ ]
Lazy patterns
6
7
8
9
> s t a c k E m p t y : : S t a c k a −> Bool
> s t a c k E m p t y ( St [ ] )
= True
> s t a c k E m p t y ( St _)
= False
10
11
12
Pattern
Matching
> push : : a −> S t a c k a −> S t a c k a
> push
x
( St x s ) = St ( x : x s )
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Stack-Implementierung (1)
Universität Bielefeld
Programmieren
1
2
> module S t a c k ( Stack , emptyStack , stackEmpty , pop , push ,in Haskell
top )
> data S t a c k a = St [ a ]
Giegerich
3
4
5
> emptyStack : : Stack a
> e m p t y S t a c k = St [ ]
Lazy patterns
6
7
8
9
> s t a c k E m p t y : : S t a c k a −> Bool
> s t a c k E m p t y ( St [ ] )
= True
> s t a c k E m p t y ( St _)
= False
10
11
12
Pattern
Matching
> push : : a −> S t a c k a −> S t a c k a
> push
x
( St x s ) = St ( x : x s )
Der Datentyp stack wird exportiert, aber nicht der Konstruktor St!
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
NUR mittels Emptystack und push können Stacks erzeugt werden.
Stack
Queue
Alternative: module Stack (Stack(St), emptyStack ...
oder auch module Stack (Stack(..), emptyStack ...
Set
Multi-Set
Stack-Implementierung (2)
Universität Bielefeld
Programmieren
in Haskell
Giegerich
14
15
16
> pop : : S t a c k a
> pop ( St [ ] )
> pop ( St ( x : x s ) )
−> S t a c k a
= e r r o r " pop : S t a c k empty ! "
= St x s
17
18
19
20
> t o p : : S t a c k a −> a
> t o p ( St [ ] )
= e r r o r " t o p : S t a c k empty ! "
> t o p ( St ( x : x s ) ) = x
Inspektion und Abbau von Stacks
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Sicherheit ...
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Welche Rolle spielt der Konstruktor St?
unterhalb von St stehen immer nur einfache Listen
Lazy patterns
Prüfungen,
Vorbereitung
eigentlich kann man ihn ganz weglassen, oder?
Abstrakte
Datentypen
wie z.B. in ...
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Schlichte Stacks...
1
2
Programmieren
> module S t a c k 2 ( Stack , emptyStack , stackEmpty , pop , push
, top )
in Haskell
> type S t a c k a = [ a ]
Giegerich
3
4
5
> emptyStack : : Stack a
> emptyStack = [ ]
6
7
8
9
11
Lazy patterns
Prüfungen,
Vorbereitung
> push : : a −> S t a c k a −> S t a c k a
> push
x
xs
= x : xs
Haskell
Modules
13
14
15
16
> pop : : S t a c k a −> S t a c k a
> pop
[]
= e r r o r " pop : S t a c k empty ! "
> pop ( x : x s )
= xs
19
20
Abstrakte
Datentypen
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
17
18
Pattern
Matching
> s t a c k E m p t y : : S t a c k a −> Bool
> stackEmpty
[]
= True
> stackEmpty
_
= False
10
12
Universität Bielefeld
> t o p : : S t a c k a −> a
> top
[]
= e r r o r " t o p : S t a c k empty ! "
> top
( x : xs ) = x
Multi-Set
Der Unterschied ...
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Den Unterschied sieht man mit Hugs an Ausdrücken wie
push ’y’ emptyStack
emptyStack ++ "nonono"
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Der Unterschied ...
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Den Unterschied sieht man mit Hugs an Ausdrücken wie
push ’y’ emptyStack
emptyStack ++ "nonono"
Auf den “schlichten” Stacks sind normale Listenoperationen
ausführbar – das will man gerade nicht, auch wenn es
manchmal praktisch wäre, so wie im Falle von show.
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Konvertierung
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
1
2
Die erste Lösung ist also die bessere. Ggf. brauchen wir
Konvertierungsfunktionen zwischen Listen und Stacks.
> l2s :: [ a ] -> Stack a
> s2l : Stack a -> [ a ]
Wo würde man die implementieren?
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Konvertierung wo?
Universität Bielefeld
Programmieren
in Haskell
Giegerich
1
2
Im Modul Stack geht es einfach und effizient:
> l2s l
= St l
> s2l ( St l ) = l
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Konvertierung wo?
Universität Bielefeld
Programmieren
in Haskell
Giegerich
1
2
1
2
3
Im Modul Stack geht es einfach und effizient:
> l2s l
= St l
> s2l ( St l ) = l
außerhalb geht es auch recht einfach, aber weniger effizient:
> l2s = foldr push emptyStack l
> s2l s = if s == emptyStack then []
>
else top s : s2l pop s
Das liegt daran, dass wir “außen” nichts über die interne
Implementierung wissen.
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Beispiel: Queue
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Warteschlangen realisiert der ADT Queue.
Eine Queue (Schlange) arbeitet (im Gegensatz zum Stack)
nach dem FIFO (First In First Out)-Prinzip
→ das erste Element, das einer Queue hinzugefügt wurde, ist
auch das erste, das wieder entfernt wird
Eine Queue stellt die Operationen enqueue, dequeue und
front bereit, sowie emptyQueue und queueEmpty.
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Queue-Schnittstelle in Haskell
1
2
Universität Bielefeld
module Queue ( Queue , emptyQueue , queueEmpty ,
enqueue , dequeue , front ) where
3
4
5
6
7
8
emptyQueue
queueEmpty
enqueue
dequeue
front
::
::
::
::
::
Queue a
Queue a ->
a -> Queue
Queue a ->
Queue a ->
Programmieren
in Haskell
Giegerich
Pattern
Matching
Bool
a -> Queue a
Queue a
a
emptyQueue liefert eine neue Queue
queueEmpty überprüft, ob eine Queue leer ist
enqueue fügt einer Queue ein neues Element hinzu
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
dequeue entfernt das erste Element aus der Queue
Set
Multi-Set
front liefert das erste Element der Queue
Queue Implementierung (0)
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Vorüberlegung:
Warum kann es nicht effizient werden, Queues einfach als
Listen zu implementieren?
Also z.B. als
data Queue a = Q [a] ?
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Queue Implementierung (1)
Universität Bielefeld
Programmieren
in Haskell
Giegerich
1
2
Moduldeklaration:
Pattern
Matching
> module Queue ( Queue , emptyQueue , queueEmpty ,
>
enqueue , dequeue , f r o n t ) where
Lazy patterns
3
4
5
6
7
8
>
>
>
>
>
emptyQueue
queueEmpty
enqueue
dequeue
front
::
::
::
::
::
Queue a
Queue a −>
a −> Queue
Queue a −>
Queue a −>
Bool
a −> Queue a
Queue a
a
Auch hier wird kein Konstruktor exportiert!
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Queue Implementierung (1)
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Aufbau einer Queue:
10
> data Queue a = Q [ a ] [ a ] d e r i v i n g ( Show , Eq )
11
12
13
14
> emptyQueue
> queueEmpty (Q [ ]
> queueEmpty _
= Q [] []
[ ] ) = True
= False
15
16
> e n q u e u e a (Q back f r o n t )
= Q ( a : back ) f r o n t
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Queue Implementierung (3)
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Abbau einer Queue:
Pattern
Matching
17
18
19
20
> d e q u e u e (Q [ ] [ ] )
= e r r o r " d e q u e u e : queue empty ! "
Lazy patterns
> d e q u e u e (Q back [ ] )
= d e q u e u e (Q [ ] ( r e v e r s e back
))
Prüfungen,
> d e q u e u e (Q back ( a : f r o n t ) ) = Q back f r o n t
Vorbereitung
21
22
23
24
> f r o n t (Q [ ] [ ] )
> f r o n t (Q back [ ] )
> f r o n t (Q back ( a : f r o n t ) )
= e r r o r " f r o n t : queue emptyAbstrakte
!"
Datentypen
= f r o n t (Q [ ] ( r e v e r s e backHaskell
))
= a
Modules
DatentypSpezifikationen
Natürlich verwenden wir eine O(n)-Implementierung von
reverse
Holy Lists
Stack
Queue
Set
Multi-Set
Queue: Effizienz?
Universität Bielefeld
Programmieren
in Haskell
emptyQueue liefert eine neue Queue
queueEmpty überprüft, ob eine Queue leer ist
enqueue fügt einer Queue ein neues Element hinzu
dequeue entfernt das erste Element aus der Queue
front liefert das erste Element der Queue
Effizienzbetrachtung:
Welchen Rechenaufwand haben die einzelnen
Operationen?
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Was ist der Aufwand, wenn n Eintraege erzeugt, gelesen
und entfernt werden?
Stack
Queue
Set
Multi-Set
Queue: Effizienz?
Universität Bielefeld
Programmieren
in Haskell
emptyQueue liefert eine neue Queue
queueEmpty überprüft, ob eine Queue leer ist
enqueue fügt einer Queue ein neues Element hinzu
dequeue entfernt das erste Element aus der Queue
front liefert das erste Element der Queue
Effizienzbetrachtung:
Welchen Rechenaufwand haben die einzelnen
Operationen?
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Was ist der Aufwand, wenn n Eintraege erzeugt, gelesen
und entfernt werden?
Amortisierte Effizienz von O(1) für dequeue.
Stack
Queue
Set
Multi-Set
Varianten
Universität Bielefeld
Programmieren
in Haskell
Was ändert sich, wenn man front und dequeue zusammenlegt
als frondeq:: Queue a -> (a, Queue a) ?
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Varianten
Universität Bielefeld
Programmieren
in Haskell
Was ändert sich, wenn man front und dequeue zusammenlegt
als frondeq:: Queue a -> (a, Queue a) ?
1
2
3
> frondeq ( Q [] []) = error " front : empty queue ! "
> frondeq ( Q back []) = frondeq ( Q [] ( reverse back ))
> frondeq ( Q back ( a : front )) = (a , Q back front )
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Varianten
Universität Bielefeld
Programmieren
in Haskell
Was ändert sich, wenn man front und dequeue zusammenlegt
als frondeq:: Queue a -> (a, Queue a) ?
1
2
3
> frondeq ( Q [] []) = error " front : empty queue ! "
> frondeq ( Q back []) = frondeq ( Q [] ( reverse back ))
> frondeq ( Q back ( a : front )) = (a , Q back front )
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Jedes Element wird nur einmal gelesen und nur einmal
revertiert.
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Varianten
Universität Bielefeld
Programmieren
in Haskell
Was ändert sich, wenn man front und dequeue zusammenlegt
als frondeq:: Queue a -> (a, Queue a) ?
1
2
3
> frondeq ( Q [] []) = error " front : empty queue ! "
> frondeq ( Q back []) = frondeq ( Q [] ( reverse back ))
> frondeq ( Q back ( a : front )) = (a , Q back front )
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Jedes Element wird nur einmal gelesen und nur einmal
revertiert.
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Nochmals die Sinnfrage:
Warum kann man ohne abstrakte Datentypen den Typ Queue
nicht korrekt implementieren?
Stack
Queue
Set
Multi-Set
Beispiel: Mengen
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Mengen sind ein recht schwieriger Datentyp.
Eine Menge ist eine ungeordnete Sammlung von
unterschiedlichen Elementen
Ein Element kann auf Mitgliedschaft in einer Menge hin
überprüft werden, kann einer Menge hinzugefügt oder aus
einer Menge entfernt werden
Was ist daran schwierig?
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Mengen-Schnittstelle in Haskell
1
2
module Set ( Set , emptySet , setEmpty , inSet ,
addSet , delSet ) where
Universität Bielefeld
Programmieren
in Haskell
Giegerich
3
4
5
6
7
8
emptySet
setEmpty
inSet
addSet
delSet
::
::
::
::
::
Set
Set
( Eq
( Eq
( Eq
a
a -> Bool
a ) = > a -> Set a -> Bool
a ) = > a -> Set a -> Set a
a ) = > a -> Set a -> Set a
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Mengen-Schnittstelle in Haskell
1
2
module Set ( Set , emptySet , setEmpty , inSet ,
addSet , delSet ) where
Universität Bielefeld
Programmieren
in Haskell
Giegerich
3
4
5
6
7
8
emptySet
setEmpty
inSet
addSet
delSet
::
::
::
::
::
Set
Set
( Eq
( Eq
( Eq
a
a -> Bool
a ) = > a -> Set a -> Bool
a ) = > a -> Set a -> Set a
a ) = > a -> Set a -> Set a
emptySet erzeugt eine leere Menge
setEmpty überprüft, ob die Menge leer ist
inSet überprüft, ob ein Element in einer Menge enthalten
ist
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
addSet fügt ein Element der Menge hinzu
delSet entfernt ein Element aus der Menge
Multi-Set
Mengen-Implementierung
Universität Bielefeld
Programmieren
in Haskell
Giegerich
Pattern
Matching
Lazy patterns
Siehe Datei set.lhs
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Multi-Set
Universität Bielefeld
Programmieren
in Haskell
Synonyme:
Multimenge
Multi-Set
Bag
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Multi-Set
Universität Bielefeld
Programmieren
in Haskell
Synonyme:
Multimenge
Multi-Set
Giegerich
Pattern
Matching
Lazy patterns
Bag
Prüfungen,
Vorbereitung
die Elementpositionen spielen keine Rolle
Abstrakte
Datentypen
→ wie bei Set
→ Unterschied zu Listen
Elemente können vielfach enthalten sein
→ Unterschied zu Set
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
→ wie bei Listen
Set
Multi-Set
Multimenge
Universität Bielefeld
Programmieren
in Haskell
∅ die leere Multimenge,
Giegerich
*a+ die einelementige Multimenge, die genau ein
Vorkommen von a enthält,
x ] y die Vereinigung der Elemente von x und y ; das
„+“ im Vereinigungszeichen deutet an, dass sich
die Vorkommen in x und y akkumulieren.
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
∅]x =
x
x ]∅=
x
x ]y =
y ]x
(x ] y ) ] z =
x ] (y ] z)
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Multimenge
Universität Bielefeld
Programmieren
in Haskell
Giegerich
1
2
3
bag :: [ a ] -> Bag a
bag []
= ∅
bag ( a : as ) = *a+ ] bag as
Beobachtung
Eine Liste x enthält alle Elemente von y , falls bag x = bag y .
In diesem Fall heißt x Permutation von y .
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Abstrakter Datentyp Multimenge
Universität Bielefeld
Programmieren
in Haskell
1
2
3
4
module Bag ( Bag , emptyBag , bagEmpty , inBag ,
addBag , delBag , appendBag ,
eqBag ) where
import List
5
6
7
8
9
10
11
12
emptyBag
bagEmpty
inBag
addBag
delBag
appendBag
eqBag
::
::
::
::
::
::
::
Bag a
Bag a -> Bool
Eq a = > a -> Bag a -> Bool
Eq a = > a -> Bag a -> Bag a
Eq a = > a -> Bag a -> Bag a
Bag a -> Bag a -> Bag a
Eq a = > Bag a -> Bag a -> Bool
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Abstrakter Datentyp Multimenge
Universität Bielefeld
Programmieren
in Haskell
emptyBag erzeugt eine neue Multimenge
bagEmpty überprüft, ob eine Multimenge leer ist
inBag überprüft, ob ein Element in der Multimenge
enthalten ist
addBag fügt ein Element einer Multimenge hinzu
delBag löscht ein Element aus einer Multimenge
appendBag vereinigt zwei Multimengen
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Abstrakter Datentyp Multimenge
Universität Bielefeld
Programmieren
in Haskell
emptyBag erzeugt eine neue Multimenge
bagEmpty überprüft, ob eine Multimenge leer ist
inBag überprüft, ob ein Element in der Multimenge
enthalten ist
addBag fügt ein Element einer Multimenge hinzu
delBag löscht ein Element aus einer Multimenge
appendBag vereinigt zwei Multimengen
Was soll man von diesen Operationen halten?
Giegerich
Pattern
Matching
Lazy patterns
Prüfungen,
Vorbereitung
Abstrakte
Datentypen
Haskell
Modules
DatentypSpezifikationen
headBag gibt das erste Element aus der Multimenge aus
Holy Lists
tailBag entfernt das erste Element aus der Multimenge
Queue
Siehe Datei bag.lhs
Stack
Set
Multi-Set
ADT-Fazit
Universität Bielefeld
Programmieren
in Haskell
Giegerich
ADTs sind wesentlich für die nachhaltige Software-Entwicklung.
Einzelne Programmteile können unabhängig voneinander
Pattern
Matching
Lazy patterns
entwickelt
Prüfungen,
Vorbereitung
verbessert und erweitert
Abstrakte
Datentypen
ausgetauscht werden
Haskell
Modules
und haben klare Schnittstellen (auch für das Verstehen des
Programms)
DatentypSpezifikationen
Holy Lists
Stack
Queue
Set
Multi-Set
Herunterladen