Berthold Hoffmann [email protected] Funktionales Programmieren Programmieren imperativ objektorientiert regelbasiert funktional logisch Modul 03-BA-700.03, Praktische Informatik 3 Wintersemester 2011/2012 Fachbereich Mathematik und Informatik – Universität Bremen Vorbemerkungen Dieser Text beschreibt den Inhalt der Lehrveranstaltung Praktische Informatik 3 im 3. Semester des Informatikstudiums an der Universität Bremen. Diese Veranstaltung behandelt alles, was jeder Studierende der Informatik über funktionales Programmieren wissen sollte. Weitere Informationen zur Veranstaltung finden sich an zwei Stellen: • • über stud.ip können die Studierenden sich Tutorien zuordnen, übungsaufgaben lesen und abgeben, und sich Termine für Fachgespräche reservieren. Hier können auch im Forum Fragen zur Veranstaltung diskutiert werden. Unter der url www.informatik.uni-bremen.de/agbkb/lehre/pi3/ stehen dieser Text, Handbücher zur verwendeten Programmiersprache Haskell und der benutzen Implementierung ghci zur Verfügung. Dieser Text ist sicher nicht perfekt. Hinweise auf Fehler aller Art und Anregungen für Verbesserungen werden gerne entgegengenommen und – soweit möglich – in zukünftige Fassungen berücksichtigt. Bremen, 2. November 2011 Berthold Hoffmann Inhaltsverzeichnis 1 Einführung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.1 Das Wesentliche beim Programmieren . . . . . . . . . . . . . . . . . . . . . 1.2 Programmieren – eine kleine Stilkunde . . . . . . . . . . . . . . . . . . . . . 1.3 Von der Methode zur Funktion . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.4 Funktionales Programmieren in der Nussschale . . . . . . . . . . . . . . 1.5 Wozu funktional programmieren? . . . . . . . . . . . . . . . . . . . . . . . . . . 1.6 Übungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.7 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.8 Geschichte des funktionalen Programmierens . . . . . . . . . . . . . . . . 1.9 Lehrbücher zum Kurs . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1.10 Haskells Eck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 1 1 2 3 5 12 13 14 14 16 17 2 Standardtypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.1 Einfache Standardtypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.2 Zusammengesetzte Standardtypen . . . . . . . . . . . . . . . . . . . . . . . . . 2.3 Fragen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2.4 Haskells Eck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19 19 27 32 32 3 Listen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.1 Vordefinierte Listenfunktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.2 Listenumschreibungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.3 Rekursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3.4 Haskells Eck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 35 35 37 40 46 4 Funktionen höherer Ordnung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.1 Listenkombinatoren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.2 Rechnen mit Funktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.3 Funktionsräume als Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . 4.4 Programmentwicklung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 51 51 55 59 61 5 Algebraische Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.1 Aufzählungstypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.2 Produkttypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.3 Summentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.4 Rekursive algebraische Datentypen . . . . . . . . . . . . . . . . . . . . . . . . 5.5 Bäume . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 5.6 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 65 65 67 69 72 73 76 6 Abstrakte Datentypen I . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.1 Konkrete und abstrakte Datentypen . . . . . . . . . . . . . . . . . . . . . . . 6.2 Kapselung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6.3 Klassische abstrakte Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . 6.4 Haskells Eck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 79 79 82 85 89 7 Mehr Abstrakte Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 91 7.1 Mengen als abstrakte Datentypen . . . . . . . . . . . . . . . . . . . . . . . . . 91 7.2 Abschließende Bemerkungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 7.3 Haskells Eck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 101 8 Zustand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 8.1 Funktionen mit Seiteneffekten . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 105 9 Ein-Ausgabe . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 9.1 Zustände und Seiteneffekte . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 113 9.2 Aktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 115 9.3 Die do-Notation . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 117 9.4 Das Nim-Spiel . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 118 9.5 Ein- Ausgabe von Dateien . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 120 9.6 Kombination von Aktionen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 121 9.7 Monaden . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 123 9.8 Haskells Eck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 124 9.9 Zusammenfassung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 10 Verzögerte Auswertung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 10.1 Auswertung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 127 10.2 Daten-orientierte Programme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 130 10.3 Ströme . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 133 10.4 Fallstudie: Parsieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 135 10.5 Haskells Eck . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 146 11 Feld und Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 11.1 Feld . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 149 11.2 Graph . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 152 vi 12 Beweise und Typen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 12.1 Formalisierung und Beweis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 157 12.2 Typinferenz . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 165 13 Aufwand . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 173 13.1 Komplexität funktionaler Programme . . . . . . . . . . . . . . . . . . . . . . 173 13.2 Endrekursion . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 176 13.3 Striktheit . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 180 13.4 Gemeinsame Teilausdrücke . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 181 13.5 Listen und Felder . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 182 14 Rückblick und Ausblick . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 14.1 Logik-Programmieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 187 14.2 Funktionales Programmieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 189 Literaturverzeichnis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 195 Lösungen für Übungen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 A.1 Lösungen für Übungen 1.6 auf Seite 13 . . . . . . . . . . . . . . . . . . . . . 199 Bibliographical Notes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 199 Haskell B.1 B.2 B.3 B.4 B.5 ausführen und dokumentieren . . . . . . . . . . . . . . . . . . . . . . . . . 201 Haskell ausführen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 201 Haskell dokumentieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 202 Haskell literarisch beschreiben . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203 Haskell-Aufgaben literarisch dokumentieren . . . . . . . . . . . . . . . . . 204 Haskell poetisch formatieren . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 205 Haskell C.1 C.2 C.3 C.4 C.5 C.6 C.7 C.8 C.9 . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 207 Der Kern funktionaler Sprachen . . . . . . . . . . . . . . . . . . . . . . . . . . . 208 Typisierung . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 210 Basis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 213 Syntaktischer Zucker . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 214 Klassen . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 217 Programme und Module . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 219 No-Fun-Haskell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 220 Die lexikalische Struktur . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 221 Lexikon . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 225 Syntaktischer Zucker in Haskell . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 227 Untergrund . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 E.1 Inferenzregeln . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 E.2 Lambda-Kalkül . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 230 vii Glossar . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 229 (Dies ist Fassung 2.0 von 2. November 2011.) viii