521
Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit¨ at Konstanz Sommer 2016 Folien basieren teilweise auf fr¨ uheren Lehrveranstaltungen von M. Scholl und T. Grust.

Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

  • Upload
    others

  • View
    4

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

Informatik 2Konzepte der Programmierung

(& Programmierkurs 2)

Stefan Klinger

LS Scholl, Datenbanken und InformationssystemeUniversitat Konstanz

Sommer 2016

Folien basieren teilweise auf fruheren Lehrveranstaltungen von M. Scholl und T. Grust.

Page 2: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0Einleitung

Page 3: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Das Modul Informatik 2 · 0.1

0.1 Das Modul Informatik 2

Zwei Lehrveranstaltungen:

Konzepte der Programmierung (KdP) Hier werden hauptsachlich dietheoretischen Konzepte vermittelt.

Programmierkurs 2 (PK2) Praktische Diskussion und Anwendung derTheorie aus KdP.

⇒ Beide Veranstaltungen bilden eine Einheit!

I Man kann nicht nur an PK2 xor KdP teilnehmen.

I Massiver Kontakt mit Quellcode auch in der KdP Vorlesung.

I PK2 greift auf Stoff aus der KdP Vorlesung zuruck und vertieft diesen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 3

Page 4: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Das Modul Informatik 2 · 0.1

Informatik 2 im ersten Semester?

Fur Erstsemester (= Sommeranfanger) ...

I ist diese Veranstaltung moglich,

I empfohlen wird i.d.R. Theoretische Grundlagen der Informatik undInformatik 2 im dritten Semester.

I KdP und PK2 sind nicht so praxisorientiert wie sich das anhort.

I Wer trotzdem mochte, sollte im Bruckenkurs Mathematik von Dr. Kosubgewesen sein.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 4

Page 5: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Das Modul Informatik 2 · 0.1

Wieviel Arbeit ist Informatik 2? Faustregel: Heimarbeit ≈ 2× Vorlesung

I Konzepte der Programmierung (KdP): 4c Einheit c fur Credits.

I Programmierkurs 2 (PK2): 5c

I Nach ECTS1 gilt: 1c ≡ 30h Einheit h fur Stunden.

I Dieses Semester: 14w Einheit w fur Wochen.

(4c + 5c) · 30hc

14w≈ 19.29

h

w

I 4 hw fur die Vorlesung KdP (eigentlich nur 3h), plus

I 2 hw fur die Vorlesung PK2 (eigentlich nur 1.5h), plus

I 2 hw fur das Tutorium (eigentlich nur 1.5h), plus

I 11.29 hw zum Nachbearbeiten und zum Losen der Ubungsblatter.

1http://de.wikipedia.org/wiki/European_Credit_Transfer_SystemStefan Klinger · DBIS Informatik 2 · Sommer 2016 5

Page 6: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Das Modul Informatik 2 · 0.1

Literatur

I Umfassendes Folienscript. Zusammen mit PK2-Material vollkommenausreichend fur die Klausur.

I Bei weiterem Interesse:• Richard Bird, Philip Wadler2. Introduction to Functional Programming using

Haskell. 2. Ausgabe, 1998, Prentice Hall. ISBN 0-13-484346-0.• J. Mitchell. Concepts in Programming Languages. 2002, Cambridge

University Press. ISBN 978-0-521-78098-8.

2nur in der ersten AuflageStefan Klinger · DBIS Informatik 2 · Sommer 2016 6

Page 7: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Koordinaten · 0.2

0.2 Koordinaten

Material https://svn.uni-konstanz.de/dbis/inf2_16s/pubFolien, Ubungsblatter, Code. Wird regelmaßig aktualisiert.

Vorlesungen immer 15:15–16:45

PK2 Montag, R513“Hands on” Programmieren.

KdP Dienstag, A701 und Mittwoch, R513Theoretische Konzepte und Einfuhrung in Haskell.

⇒ Beide Veranstaltungen bilden eine Einheit!

Tutorien finden Donnerstags und Freitags statt (cf. Seite 10).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 7

Page 8: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Koordinaten · 0.2

Subversion

I Alle Materialien werden uber Subversion3 verwaltet.Siehe Schlusselqualifikation, 1. Semester.

I Aus dem Repository4 sind zwei Unterverzeichnisse fur Sie relevant:

/pub Materialien aus der Vorlesung und Ubungsblatter, wird von unsaktualisiert, Sie haben nur Leserechte.

/group/foo Bearbeitung und Abgabe der Losungen. JedeUbungsgruppe (hier: foo) bekommt ein Unterverzeichnis. Dort dieLosungen zu den wochentlichen Ubungen rechtzeitig eincheken!

• Authentifizierung uber Uni-ID, also user & passwd wie fur Uni-Mail.• Den Namen der Gruppe erfahren Sie nach der Anmeldung fur ein Tutorium.

⇒ Weitere Infos auf dem 1. Ubungsblatt.

3http://subversion.apache.org/4https://svn.uni-konstanz.de/dbis/inf2_16s (Leserechte nur in genannten Unterverzeichnissen)Stefan Klinger · DBIS Informatik 2 · Sommer 2016 8

Page 9: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Koordinaten · 0.2

Tutorien Termine cf. Seite 10

Inhalt

I Tutoren stellen Musterlosungen vor.

I Fragen zur eigenen Losung stellen.

I Besprechen von Konzepten, die in der Vorlesung nicht ganz klargeworden sind.

I Elaborierte Fragen stellen.

I evtl. Tips von den Tutoren zur Losung der nachsten Aufgaben.

I Die Initiative geht von Ihnen aus!

Obacht

I Voraussetzung: Intensive Auseinandersetzung mit Stoff und Ubungsblattvor dem Tutorium.

I Die Ubungen lassen sich nicht im Rahmen der Tutorien bearbeiten!

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 9

Page 10: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Koordinaten · 0.2

Personal

Prof. Marc Scholl LS Datenbanken und Informationssysteme (DBIS)

web http://dbis.uni-konstanz.de/office PZ811

Stefan Klinger Ich halte die Vorlesungen KdP und PK2

mail [email protected] PZ804

Die Tutoren

Stefan Erk (A) Do 13:30, [email protected]

Johannes Fuchs evtl. zwei Tutorien:(B) Do 15:15, F428, und(C) Do 17:00, [email protected]

Denis Gietz (D) Fr 8:15, [email protected]

Robert Schmid (E) Fr 10:00, [email protected]

Fabian Spah (F) Fr 11:45, [email protected]

Der im LSF angegebene Termin G, Fr 15:15 wird nicht angeboten.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 10

Page 11: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Prufung · 0.3

0.3 Prufung

I Eine gemeinsame Klausur fur PK2 und KdP.• Nur bei Bestehen der Klausur werden die ECTS-Punkte fur PK2 und KdP

gutgeschrieben.

I Ein Ubungsblatt pro Woche (fur PK2 und KdP zusammen).• Ausgabe am Montag, Abgabe bis jeweils nachsten Montag, 15:00.• Blatter werden in 2er-Teams bearbeitet.• Klausur am Ende des Semesters bestimmt Note fur KdP.• Klausurzulassung ⇒ 50% der Ubungspunkte erreicht.

I Ab diesem Semester ist die Prufungsanmeldung (cf. Seite 12) zwingendnotwendig.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 11

Page 12: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Anmeldung · 0.4

0.4 Anmeldung — Wichtig ← das ist nicht zum Spaß rot

Prufungsanmeldung Sie mussen sich innerhalb des Anmeldezeitraums5

via StudIS6 verbindlich zur Prufung anmelden. Und zwar fur beideVeranstaltungen, KdP und PK2. cf. Info des Fachbereichs

Diese Woche Anmeldung per Mail, wie auf dem ersten Ubungsblattbeschrieben7. Frist: Mittwoch Abend, 18 Uhr

I Bildung der 2er-Teams fur die Ubungen, und Verteilung auf die Tutorien.I Wenn sie sich fruhzeitig anmelden, haben Vorrang bei der Terminwahl:

• Eltern mit StEP8, und• Fachfremde bei nachgewiesener Kollision mit einer anderen Pflichtvorlesung.

5http://www.informatik.uni-konstanz.de/studieren/studium/pos-pruefungsinformationen/pruefungsanmeldung/

6https://studis.uni-konstanz.de/7https://svn.uni-konstanz.de/dbis/inf2_16s/pub/assignment01.pdf8http://www.familie.uni-konstanz.de/programme-fuer-eltern/studieren-mit-kind/

der-studierenden-elternpass/Stefan Klinger · DBIS Informatik 2 · Sommer 2016 12

Page 13: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Anmeldung · 0.4

Noch Fragen zur Organisation?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 13

Page 14: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Konzepte der Programmierung · 0.5

0.5 Konzepte der Programmierung

Je nach Zahlung gibt es >50 Paradigmen (Konzepte), die sich nichtgegenseitig ausschließen.

Eine ubliche Einteilung mit prominenten Vertretern:I Imperative Sprachen

• Strukturiert: Python, C, C++, Java Beispiel cf. Seite 15

• Objektorientiert: Python, C++, Java

I Deklarative Sprachen• Funktionale Sprachen: Haskell, Erlang, JS Beispiel cf. Seite 18

Haskell entstand, um state-of-the-art FPL-Forschung in einer Sprache zusammenzufuhren.

Prominente Entwickler: Simon Peyton Jones, Philip Wadler, ...

• Logische Sprachen: Prolog, Datalog Beispiel cf. Seite 19

Programmation en Logique. Initial: Alain Colmerauer, 1972. Viele Ableger.

• Datenbanksprachen wie SQL oder XQuery cf. Modul Datenbanken!

Werfen wir einen kurzen Blick auf drei Vertreter...

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 14

Page 15: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Konzepte der Programmierung · 0.5

Imperativ — Quicksort in Java

1 private static void quicksort(int[] a, int from, int to) {2

3 if (to - from > 0) {4

5 int pivot = to; int l = from, r = to - 1;

6

7 while (l < r) {8 while ((l < r) && (a[l] <= a[pivot])) { l++; }9 while ((l < r) && (a[r] >= a[pivot])) { r--; }

10 if (l != r) {11 swap(a, l, r);

12 } else if (a[l] > a[pivot]) {13 swap(a, l, pivot);

14 }15 }16

17 quicksort(a, from, l - 1);

18 quicksort(a, l + 1, to);

19

20 }21 }

Code aus der KdI-Vorlesung von Dr. Meinl

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 15

Page 16: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Konzepte der Programmierung · 0.5

Frage Was passiert da?

1. Auswahl eines beliebigen Elements der Liste, sog. Pivotelement p.

2. Verschieben des Pivotlements in der Liste, so dass• alle Elemente links von p kleiner als p sind, und• alle Elemente rechts von p großer oder gleich p sind.

⇒ Damit ist das Pivotelement bereits an seiner endgultigen Position.

3. Rekursives Sortieren der linken und rechten Teilliste.

I Als Pivotelement kann man z.B. das rechteste Element der Liste wahlen.I Verschieben des Pivotelements:

1. Suche von links nach einem Element xi mit xi > p,2. suche von rechts nach einem Element xj mit xj < p,3. und vertausche die beiden Elemente.4. Solange wiederholen, bis sich i und j treffen.5. Pivotelement mit Element an Position i vertauschen, falls p < xi .

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 16

Page 17: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Konzepte der Programmierung · 0.5

Beispiel:

512 170 61 897 908 87 503 415

415

415

512 170 61 897 908 87 503

87 170 61 897 908 512 503

89787 170 61 415 908 512 503

I Jetzt noch rekursiv die beiden Teillisten links und rechts von 415sortieren.

Grafik aus der KdI-Vorlesung von Dr. Meinl

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 17

Page 18: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Konzepte der Programmierung · 0.5

Funktional — Quicksort in Haskell

1 quicksort [] = []

2

3 quicksort (x:xs)

4 = quicksort (filter (<x) xs) ++ [x] ++ quicksort (filter (>=x) xs)

I Dabei ist• [] die leere Liste,• (x:xs) die Liste mit erstem Element x und Restliste xs,• [x] die Liste mit einem Element x,• ++ die Listen-Konkatenation,• filter p filtert die Elemente aus einer Liste, die p erfullen.

I Benutzung:

1 *Main> quicksort [5,7,2,6,8,1,4,3,0,1]

2 [0,1,1,2,3,4,5,6,7,8]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 18

Page 19: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Konzepte der Programmierung · 0.5

Logisch — Pfadsuche in Prolog

Ein Prolog-Programm besteht aus Fakten und Regeln. Etwa:

I Fakten: Eine Datenbank mit Flugverbindungen.

1 leg(fdh, cgn). leg(fdh, fra).

2 leg(fra, sin). leg(fra, cgn).

3 leg(sin, syd). leg(sin, chc).

4 leg(cgn, sin). leg(cgn, gla).

5 leg(gla, sin).fdh

cgn

fra

sin

gla

syd

chc

I Regeln: Fliegen mit Zwischenstop.

6 route(A, B, []) :- leg(A, B).

7 route(A, B, [X|XS]) :- leg(A, X), route(X, B, XS).

I Gegen diese Wissensbasis konnen Anfragen formuliert werden:

Uber welche Route Q kommeich von Frankfurt nachSingapore?

1 ?- route(fra, sin, Q).

2 Q = [] ;

3 Q = [cgn] ;

4 Q = [cgn, gla] ;

5 false.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 19

Page 20: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Konzepte der Programmierung · 0.5

I Diese Anfragen konnen auch mehrere freie Variablen aufweisen:

Wohin ab Friedrichshafenmit genau einemZwischenstopp?

1 ?- route(fdh, B, [X]).

2 B = sin, X = cgn ;

3 B = gla, X = cgn ;

4 B = sin, X = fra ;

5 B = cgn, X = fra ;

6 false.

• Hier steht [X] fur eine Liste mit nur einem Element X.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 20

Page 21: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Konzepte der Programmierung · 0.5

Erste Beobachtungen

I Die gezeigten Sprachenunterscheiden sich stark: Sie“sehen anders aus”.

I Auch das Denkmodell ist jeweilsein anderes: Sie verwenden nichtnur andere Worte, sondern ganzandere Konzepte.

I In Prolog: wo ist derAlgorithmus. . . ?

I Deklarative Sprachen bieten sehrkompakte Notation.

I (Geordnete) Listen als“eingebaute” Datenstruktur.

I Pattern Matching.

I Alternative Definitionszweige.

Deklarative Programmiersprachen (im Ggs. zu imperativen):Gemeinsam ist allen deklarativen Sprachen, dass die Losung eines Problems

I (eher) auf einer hohen Abstraktionsebene spezifiziert,

I als auf einer niedrigen (Maschinen-) Ebene “ausprogrammiert” wird.

⇒ “Was und nicht wie.” (Offensichtlich ist diese Unterscheidung etwas unscharf.)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 21

Page 22: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

0 · Einleitung Inhalte der Vorlesung · 0.6

0.6 Inhalte der Vorlesung

I Eine rein funktionale Sprache lernen: Haskell

Dadurch:I Einen Einblick in verschiedene Konzepte von Programmiersprachen

bekommen.• Neue, Ihnen vermutlich unbekannte Konzepte werden eingefuhrt.

Typinferenz, Funktionen hoherer Ordnung, “unendliche” Datenstrukturen ...

• Bekannte Konzepte stehen plotzlich nicht mehr zur Verfugung,Zuweisung, Seiteneffekte, unsauberer Umgang mit Typen, ...

• oder sind ganz anders ausgepragt. Auswertestrategie, I/O, Polymorphie...

I Wir werden uns meist auf das rein funktionale Paradigmakonzentrieren, mit dem Ziel die oben “unscharf” beschriebeneUnterscheidung klarer herauszuarbeiten.

I Ein wenig die mathematischen Grundlagen von Programmiersprachenbeschnuppern.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 22

Page 23: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1Syntax & Semantik

42 - (2+1) *7

Page 24: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik

Was bedeutet 42 - (2+1) *7 — und wieso?

I Der Mensch erkennt:• Zahlen: 42, 7, 2, 1.• Bekannte Operatoren: −, ·, +.• Bekannte Rechenregeln: Punkt vor Strich, von links nach rechts, Klammerung.

I Im Geist entwickeln wir die Struktur, und rechnen (reduzieren denBaum) schrittweise entsprechend der Bedeutung:

−42 ·

+

2 1

7_

42 ·

3 7

_−

42 21

_ 21

Die Frage Wie “versteht” eine Maschine eine Programmiersprache?Mittels welcher Mechanik konnen Programmiersprachen uberhaupt etwasausdrucken?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 24

Page 25: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Ubersetzungsphasen · 1.1

1.1 Ubersetzungsphasen

I Ein Compiler (dt.: “Ubersetzer”) ist ein Programm, das Sourcecode(“Quellcode”, in einer Programmiersprache geschriebenes Programm) ineine andere Sprache ubersetzt.

I Typische Phasen beim “Verstehen” eines Programmes:

1. Lexikalische Analyse2. Syntaktische Analyse3. Semantische Analyse4. Optimierungen5. Auswerten / Erzeugen von Code

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 25

Page 26: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Ubersetzungsphasen · 1.1

Lexikalische Analyse (aka. Lexing)

Zerlegen der Eingabe 42 - (2+1) *7 in die Worte (Token) der Sprache:

4 2 - ( 2 + 1 ) * 7 7→ 42 - ( 2 + 1 ) * 7

I Man sagt: Transformiert den Byte-Stream in den Token-Stream.

I In dieser Phase wird die “Natur” der einzelnen Worte erkannt:• Erkennt welche Zeichengruppen Literale9 bilden, z.B. Zahlen (3.14, -23),

Strings ("hello world"), boolesche Werte (true), ...

• Unterscheidet z.B. Variablen (x, foo) von Schlusselworten (if, let,return, ...):

I Entfernt unnotige Leerzeichen, Zeilenumbruche und Kommentare.

1 for (i = 0; i<23; i++) {2 print(i); // Ausgabe

3 }7→ for ( i = 0 ; i < 23 ;

i ++ ) { print ( i ) ; }

9Worte die fur einen primitiven Wert stehenStefan Klinger · DBIS Informatik 2 · Sommer 2016 26

Page 27: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Ubersetzungsphasen · 1.1

Syntaktische Analyse (aka. Parsing)

I Folgen die Worte der Eingabe einer bestimmten Struktur?• Mit anderen Worten: Wird die Grammatik der Sprache erfullt?

I Diese Phase rekonstruiert die Struktur der Ausdrucks.• Entfernt Interpunktion (Klammern), die Struktur ist jetzt explizit!• Liefert den Abstract Syntax Tree (AST), der die Struktur des Ausdrucks

reprasentiert..

42 - ( 2 + 1 ) * 7 7→

-

42 *

+

2 1

7

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 27

Page 28: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Ubersetzungsphasen · 1.1

Weitere Schritte: Was passiert mit dem Programm?

I Semantische Analyse, z.B.:• Werden nur definierte Funktionen aufgerufen?• Typprufung (42+2 vs. 42+true),• ...

I Ab hier sind verschiedene Schritte moglich, z.B.:• Code in einer anderen Sprache erzeugen:

I Maschinencode der direkt auf einer CPU ausgefuhrt werden kann.I Eine wesentlich primitivere Sprache, die schlecht von Menschen, aber sehr

einfach von weiteren Phasen verstanden wird, z.B. Assembler oder JavaBytecode. (Intermediate Code)

I Eine andere Hochsprache fur die effiziente Auswertemechanismen zurVerfugung stehen (fruher gab es einen Haskell → C Compiler).

• Statt dessen konnen die Anweisungen von einem Programm auch ausgefuhrt(interpretiert) werden. Dann sagt man nicht “Compiler”, sondern“Interpreter”.

Oft finden Optimierungen als Zwischenschritte statt (Ziel: WenigerResourcenverbrauch (Rechenleistung, Speicher) des Programmes).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 28

Page 29: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Ubersetzungsphasen · 1.1

Diese Vorlesung Wir kummern uns nicht darum, wie man Compiler baut,Code optimiert oder generiert.

→ Vorlesung Compilerbau.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 29

Page 30: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Ubersetzungsphasen · 1.1

Zuruck zur Frage

Was bedeutet 42 - (2+1) *7 — und wieso?

(Wir haben bisher beschrieben was wir tun wollen, aber nicht wie das gehen soll.)

I Wie kann man Syntax und Grammatik einer Programmiersprachebeschreiben?

I Wie kann man aus dem “geschriebenen Wort” die Struktur desProgrammes rekonstruieren?

I Wie kommt man von der Struktur zur Bedeutung?

Im Folgenden befassen wir uns mit der Beschreibung von Syntax undGrammatik und dem Erkennen der Struktur.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 30

Page 31: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Regulare Ausdrucke · 1.2

1.2 Regulare Ausdrucke

Definition RegEx A — Regulare Ausdrucke uber dem Alphabet ASei x ∈ A, und seien r , s ∈ RegEx A, dann sind ebenfalls in RegEx A:

I x — Jeder einzelne Buchstabe ist auch ein Regularer Ausdruck. Dieserbeschreibt genau die Zeichenkette mit diesem einen Buchstaben.

I r∗ — Wiederholung. Beschreibt genau die Zeichenketten, die sich durchbeliebig haufiges (0 ≤ n <∞) Hintereinanderschreiben jeweils von rbeschriebener Zeichenketten bilden lassen.

I rs — Konkatenation. Beschreibt genau die Zeichenketten, die sichdurch Hintereinanderschreiben einer von r , und einer von s beschriebenenZeichenkette (in dieser Reihenfolge) bilden lassen.

I r |s — Alternative. Beschreibt genau die Zeichenketten, die durch r oders beschrieben werden.

Notation Die Operatoren sind mit absteigender Prazedenz gelistet, wirverwenden Klammern zum Gruppieren. Sei ε die leere Konkatenation.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 31

Page 32: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Regulare Ausdrucke · 1.2

Einfache Beispiele

I 2015|6|7 — Beschreibt die Zeichenfolgen 2015, 6, und 7.

I 201(5|6|7) — Beschreibt die Zeichenfolgen 2015, 2016, und 2017.

I fo∗ — Beschreibt foo, aber nicht fofofo.

I Dezimale Darstellungen der ganzen Zahlen, ohne fuhrende Null, ubereinem Alphabet A ⊇ {0, ..., 9, -}:

0∣∣ (-|ε) (1|2|3|4|5|6|7|8|9) (0|1|2|3|4|5|6|7|8|9)∗

Notation Oft findet man abkurzende Schreibweisen (r ∈ RegEx A):

I r? = r |ε — Optional.

I r+ = rr∗ — Mindestens eine Wiederholung.

I [a− z ] = a|b|...|z — genau eines der Zeichen a, b, ..., z ∈ A.Oft mehrere Zeichen und/oder Bereiche: [a− d k −mp q] = a|b|c|d

∣∣k|l |m∣∣p|qDann lautet das Beispiel fur ganze Zahlen: 0

∣∣ -? [1− 9] [0− 9]∗

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 32

Page 33: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Regulare Ausdrucke · 1.2

Beispiel: Arithmetische Ausdrucke (ohne Klammern)

Arithmetische Ausdrucke mit den ublichen Operatoren und ohneKlammern konnte man so beschreiben:

(0∣∣-?[1− 9][0− 9]∗)

((+|-|*|/) (0

∣∣-?[1− 9][0− 9]∗))∗

also etwa: Zahl(

(+|-|*|/) Zahl)∗

Problem Tatsachlich kann man prinzipiell keinen10 RegEx angeben, derirgendeine Sprache beschreibt, die auf korrekte Klammerung angewiesen ist.

⇒ Es gibt keinen RegEx, der genau die Arithmetischen Ausdrucke mitkorrekter Klammerung beschreibt.

10Beweis mit dem Pumping Lemma aus der theoretischen Informatik.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 33

Page 34: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Grammatik · 1.3

1.3 Grammatik (gibt uns die Moglichkeit zu klammern)

Definition Grammatik Weiterfuhrendes Wissen cf. Seite 52

Eine Grammatik uber einem Alphabet A besteht aus

I einer Menge N von Nonterminalen11, N ∩A = ∅,(im Gegensatz dazu werden die Elemente von A auch Terminale genannt.)

I einer Menge von Produktionen der Form

n→ r

wobei n ∈ N , und r ∈ RegEx(A ∪N ), sowie

I einem als Startpunkt ausgezeichneten Nonterminal (hier mit ? markiert).

Beispiel Grammatik fur Boolesche Ausdrucke (BoolEx), mit Klammern.Alphabet A = {T, F, &, |, !, (, )}, Nonterminale N = {Op,BoolEx}:

Op → & | |? BoolEx → T | F | ( BoolEx Op BoolEx ) | ! BoolEx

11die man sich ganz grob als “Abkurzungen” fur regulare Ausdrucke vorstellen kann.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 34

Page 35: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Grammatik · 1.3

Eine Folge von Zeichen aus dem Alphabet A erfullt eine Grammatik, wennman sie durch Anwendung der Produktionsregeln vom Startsymbolableiten kann:

BoolEx→

( BoolEx Op BoolEx )→

(T Op BoolEx )→

(T& BoolEx )→

(T&( BoolEx Op BoolEx ))→

(T&(T Op BoolEx ))→

(T&(T| BoolEx ))→

(T&(T|F))

I Zur besseren Lesbarkeit schreibt mandie Alternativen oft untereinander:

Op → &

| |

? BoolEx → T

| F

| ( BoolEx Op BoolEx )

| ! BoolEx

I Die Zeichenfolge (T&(T|F)) erfulltalso offenbar die Grammatik.

I Unsere Grammatik erlaubt keineLeerzeichen (sogar: 6∈ A).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 35

Page 36: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Grammatik · 1.3

Ableitung liefert Struktur

I Bei der Ableitung vom Startsymbol entsteht der Parse Tree (links).

( T & ( T | F ) )

BoolEx BoolEx BoolExOp Op

BoolEx

BoolEx &

T |

T F

I Der Parse-Tree enthalt bereits die Struktur des Ausdrucks (rechts):• Der |-Operator gehort zu dem BoolEx welcher rechtes Argument des

BoolEx mit dem &-Operator ist.

I Der Strukturbaum rechts heißt Abstract Syntax Tree, AST.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 36

Page 37: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Grammatik · 1.3

Leerzeichen

Eine Grammatik aufzuschreiben die alle Varianten von erlaubtenLeerzeichen in der Eingabe berucksichtigt, ist manchmal recht aufwandig.Oft wendet man ein zweistufiges Verfahren an:

1. Lexikalische Analyse ubersetzt Folge von Bytes (incl. Leerzeichen &Kommentare) in Folge von Token (ohne diese).

2. Syntaktische Analyse: Die Grammatik wird dann nicht mehr uber demAlphabet der Bytes, sondern dem Alphabet der Token definiert:

A = Z ∪ {+, -, *, /, (, )}? ArithEx → Z

| ( ArithEx Op ArithEx )

Op → + | - | * | /

I Leerzeichen spielen bei dieser Betrachtung keine Rolle mehr!I Etwas salopp (schlampig) wird hier die Menge Z auch als Nonterminal

aufgefasst, ihre Elemente als Terminale.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 37

Page 38: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Grammatik · 1.3

ArithEx→

(ArithEx Op ArithEx)→

(ArithEx Op (ArithEx Op ArithEx))→

(ArithEx Op ((ArithEx Op ArithEx) Op ArithEx))→∗

(ArithEx - ((ArithEx + ArithEx) * ArithEx))→∗

(Z - ((Z + Z) * Z))→∗

(42 - ((2 + 1) * 7))

Verbleibendes Problem Unangenehm viele Klammern, ein Paar fur jedenOperator! Man sagt, die Ausdrucke sind vollstandig geklammert.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 38

Page 39: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Klammern und Konvention · 1.4

1.4 Klammern und Konvention

Ein Hilfsmittel ausserhalb der Grammatik:

I Konvention von Prazedenz und Assoziativitat der Operatoren, und

I die Erlaubnis Klammern wegzulassen wenn ihre Position durchKonvention feststeht.

42 - 23 + 2 * 7 — Schreibweise nicht durch Grammatik gedeckt!

Konventionen wie Punkt-vor-Strich und links-Assoziativitat derOperatoren machen daraus:

((42 - 23) + (2 * 7))

Die Klammerung in 42 - 23 + 2 * 7 ist aufgrund der vereinbarten Konventionimplizit gegeben (Konvention impliziert Klammerung, im Gegensatz zurexpliziten, d.h. ausdrucklich angegebenen Klammerung).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 39

Page 40: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Klammern und Konvention · 1.4

Operatortabelle

Diese Konventionen gibt man oft in einer Operatortabelle an:

Prazedenz Operatoren Assoziativitat

8 ^ rechts7 *, / links6 +, - links

I Die Prazedenz (aka. Prioritat) wird oft in Form einer Zahl angegeben.I Die Assoziativitat gibt an, ob Operatoren der gleichen Prioritat nach

links oder nach rechts geklammert werden.

Man kann z.B. denHaskell-Interpreter danach fragen:

1 Prelude> :info + — Info uber + abfragen2 infixl 6 + — linksassoziativ, Prioritat 6

I Explizites Klammern ist dann nur noch notig, wenn die gewunschteStruktur nicht von der Konvention erzeugt wird:

((1 - (2 + 3)) + (4 * 5))

(implizite Klammern hier in Hellgrau)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 40

Page 41: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Klammern und Konvention · 1.4

Strukturbeschreibungen

I Manchmal sieht man Grammatiken wie die folgende:

Op → + | - | * | /? Expr → Z

| Expr Op Expr

I Diese Grammatik alleine reicht allerdings nicht aus um die Struktur einesAusdrucks zu erkennen: Es gibt Ausdrucke mit verschiedenenAbleitungen (Parse-Trees), die Grammatik ist nicht eindeutig!• Aufgabe: Zeige fur die Tokenfolge 10 - 6 - 2 zwei verschiedene

Ableitungen vom Startsymbol Expr.

I Trozdem kann man mit solchen Spezifikationen arbeiten (oft leichter,weil ubersichtlicher), man braucht allerdings Klammern und eineOperatortabelle wie oben. Die Klammern sind dann Teil derMetasprache (cf. Seite 45) weil sie nicht durch die Grammatikspezifiziert sind.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 41

Page 42: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Klammern und Konvention · 1.4

Man kann Grammatiken konstruieren, die auch ohne Konventionen nurdie notwendigen Klammern erzwingen:

? Sum → Sum ( + | - ) Product| Product

Product → Product ( * | / ) Singleton| Singleton

Singleton → Z| ( Sum )

I Ein Parser-Generator (aka. Compiler-Compiler) kann so eineSpezifikation verstehen und automatisch einen Parser daraus generieren.• Fur uns Menschen ist das eher schwer verstandlich! 1213

• Wir verwenden lieber “ubersichtlichere” Grammatiken mit Konventionen.• Noch haufiger lernen wir Programmiersprachen anhand von Beispielen. Nur

fur die “interessanten Randfalle” schauen wir in der Sprachdefinition nach!

12https://www.haskell.org/onlinereport/haskell2010/haskellch10.html13http://docs.oracle.com/javase/specs/jls/se8/html/jls-2.htmlStefan Klinger · DBIS Informatik 2 · Sommer 2016 42

Page 43: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Klammern und Konvention · 1.4

Grammatik gut, alles gut?

I Wir haben gesehen, dass eine einfache Grammatik nicht alleInformationen uber einen Ausdruck bereitstellen kann die wir fur dieAuswertung gerne hatten.

I Eine Grammatik fur Arithmetische Ausdrucke, die nur die notigenKlammern enthalt, ist schon arg umstandlich, cf. Seite 42.

I Im Allgemeinen konnen anhand der Grammatik nicht alle gewunschtenEinschrankungen uberpruft werden:

2/(42− 2 ∗ 21) — Division durch Null!

Spater werden wir ein Typsystem als weiteren Mechanismus kennen lernen,der die Menge der akzeptablen Programme noch genauer festlegt.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 43

Page 44: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Semantik — die Lehre von der Bedeutung · 1.5

1.5 Semantik — die Lehre von der Bedeutung

Bleibt eine Frage zu klaren:

Was bedeutet eigentlich

−42 ·

+

2 1

7— und wieso?

I Wir haben die Eingabe14 42 - ( 2 + 1 ) * 7 schrittweise auf denAST zuruckgefuhrt, und seine Bedeutung einfach angenommen.

I Tatsachlich haben wir nur die Bedeutung der Objektsprache auf einerMetaebene15 erklart, mit Hilfe einer Metasprache (gemalteBaumchen).

I Wie kommen wir vom Gemalde zur Bedeutung?

14Hier schon als Token-Stream aufgefasst.15μετά, griechisch, etwa “hinter” oder “uber”.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 44

Page 45: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Semantik — die Lehre von der Bedeutung · 1.5

Die Metaebene

Frage Wie konnen wir uberhaupt uber Sprachen sprechen?

I Die Objektsprache ist der Gegenstand (das Objekt) unserer Diskussion.

I In der Metasprache sprechen wir uber diesen Gegenstand, also uber dieObjektsprache.

Beispiele fur Sprachebenen (Notation: MetaspracheObjektsprache ).

DeutschEnglisch “Long story short.” ist eine englische Redewendung.

DeutschDeutsch

Der Zungenbrecher “Blaukraut bleibt Blaukraut undBrautkleid breibt Blautkreid.” ist auch schwer zu tippen.

DeutschArithEx

42-(2+1)*7 ist das Siebenfache der Summe von zwei undeins, abgezogen von zweiundvierzig.

MathematikBoolEx (T&(T|F)) = True ∧ (True ∨ False)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 45

Page 46: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Semantik — die Lehre von der Bedeutung · 1.5

Meta- und Meta-Metaebene

I Die gleiche Sprache kann auf Objekt- und Metaebene verwendetwerden (cf. Blaukraut-Beispiel)

I Die Unterscheidung zwischen Objekt- und Metaebene ist nicht immerganz einfach:• Konstanz hat 80’000 Einwohner. — spricht uber eine Stadt• Konstanz hat 8 Buchstaben. — spricht uber ein Wort

I Oft (immer) treten mehrere Ebenen (Meta-Metaebene, ...) auf:• Im vorigen Punkt wird (Meta2-Ebene) ein Satz analysiert, der wiederum

(Metaebene) die Anzahl der Buchstaben eines Wortes (Objekt) beschreibt.• Das war eine Aussage (Meta3) uber diese Folie...

I Wir werden die Frage nach der “wirklichen Bedeutung” also nichtabschließend klaren. (Fragen Sie einen Philosophen Ihres Vertrauens.)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 46

Page 47: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Semantik — die Lehre von der Bedeutung · 1.5

Semantische Klammern

I Zur Abgrenzung der verschiedenen Ebenen werden Ausdrucke derObjektsprache oft in semantische Klammern gesetzt.

J(T&(T|F))K ≡ True ∧ (True ∨ False)

I Man kann sich JeK als Strukturbaum des Ausdrucks e vorstellen, uberdessen Bedeutung hier eine Aussage getroffen wird.• Die genaue Bedeutung der Semantischen Klammern variiert jedoch je nach

Kontext und Autor, und wird nur bei Bedarf jeweils exakt definiert.• Tatsachlich werden auch wir J·K in unterschiedlichen Zusammenhangen

unterschiedlich verwenden...

Problem Leider konnen wir noch nicht die Bedeutung aller moglichenBoolEx beschreiben, denn es gibt unendlich viele davon, die konnen wirnicht aufzahlen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 47

Page 48: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Semantik — die Lehre von der Bedeutung · 1.5

Metavariablen

I So wie man mit J·K Terme der Objektsprache in Terme der Metaspracheeinbetten kann, mochte man auch oft Variablen der Metasprache indie Objektsprache einbetten.

Beispiel Die Semantik von BoolEx: Seien b1, b2 ∈ BoolEx.

JTK ≡ TrueJFK ≡ False

J(b1 & b2)K ≡ Jb1K ∧ Jb2KJ(b1 | b2)K ≡ Jb1K ∨ Jb2K

J!b1K ≡ ¬ Jb1K

I Hier sind b1 und b2 Metavariablen: Das Token b1 gehort nicht zurObjektsprache BoolEx, sondern zur Metaebene, und reprasentiert einen(festen, aber beliebigen) Ausdruck in BoolEx.

I z.B. muss man sich zunachst uber die Bedeutung der mit b1 und b2

benannten Ausdrucke klar weden, bevor man daraus (mittels ∧) dieBedeutung von b1 & b2 bestimmen kann.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 48

Page 49: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Semantik — die Lehre von der Bedeutung · 1.5

I Mit diesen Regeln kann man dieBedeutung eines Ausdrucks bestimmen.Nochmal die Regeln von der vorigen Folie:

JTK ≡ TrueJFK ≡ False

J(b1 & b2)K ≡ Jb1K ∧ Jb2KJ(b1 | b2)K ≡ Jb1K ∨ Jb2K

J!b1K ≡ ¬ Jb1K

I Im 1. Schritt steht z.B. die Metavariableb2 fur den Teilausdruck (T|F).

J(T&(T|F))K≡ Regel fur &

JTK ∧ J(T|F)K≡ Regel fur |

JTK ∧ (JTK ∨ JFK)≡ Regel fur T

True ∧ (True ∨ JFK)≡ Regel fur F

True ∧ (True ∨ False)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 49

Page 50: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Semantik — die Lehre von der Bedeutung · 1.5

I Sehr oft ist “klar” was zur Meta-, und was zur Objektsprache gehort.• Semantische Klammern werden dann meist weggelassen.• Man kann je Ebene eine andere Schriftart, oder einen anderen Zeichenvorrat

verwenden.

I Auch werden manchmal Symbole (z.B. Zahlen) mit Ihrer Bedeutung inmehreren Ebenen verwendet, ohne sie separat zu kennzeichnen.

I Auch in der Mathematik kann es helfen einen Schritt zuruckzutretenund sich zu fragen• woruber man eigentlich argumentiert (“Was ist das Objekt?”),• und mit welchen Mitteln man das tut (“Wie funktioniert die Metasprache?”).

I Im Lauf der Zeit werden Sie ganz selbstverstandlich und automatischmit mehreren Metaebenen gleichzeitig jonglieren...

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 50

Page 51: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Semantik — die Lehre von der Bedeutung · 1.5

Ausblick: Operationale und Denotationelle Semantik

I Die bisherige Methode Semantik zu beschreiben ist Teil der sogenanntenDenotationellen Semantik.• Ende der 1960er von Christopher Strachey und Dana Scott zur Beschreibung

der Semantik von imperativen Sprachen entwickelt.• Die semantischen Klammern J·K heißen auch Strachey brackets.

I Eine andere Art Semantik zu beschreiben, ist die OperationaleSemantik: Die Metasprache beschreibt dabei die Rechenregeln derObjektsprache, ohne Bezug zu einer “Bedeutung” auf einer Metaebene.

Beispiel Die Operationale Semantik von BoolEx: Sei b ∈ BoolEx.

T & b _ bF & b _ F

T | b _ T

F | b _ b!T _ F

!F _ T

Wie genau man damit arbeiten kann, werden wir aber erst im Kapitel uberden λ-Kalkul lernen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 51

Page 52: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Weiterfuhrendes Wissen · 1.6

1.6 Weiterfuhrendes Wissen

I In diesem Kapitel wurde eine spezielle Art von Grammatiken verwendet,namlich die sog. Kontextfreien Grammatiken (CFG).

• Es gibt unterschiedlich machtige (ausdrucksstarke) Arten vonGrammatiken.

• Die Chomsky Hierarchie liefert eine entsprechende Klassifizierung.

I Unsere Notation fur CFGn ist an die Erweiterte Backus-Naur-Form(EBNF) angelehnt.

• Eigentlich ist in Produktionen kein Regularer Ausdruckerlaubt, sondern nur eine Folge von (Non-)Terminalen.

• Rechts eine traditionelle Darstellung fur ? X→ a (b | c)∗.

• Die verwendete EBNF erlaubt es, Grammatiken deutlichkompakter und ubersichtlicher aufzuschreiben, ist abernicht machtiger.

? X → a Y

Y → Z YY → ε

Z → b

Z → c

I Algorithmen zum Lexing und Parsing: Andrew W. Appel. ModernCompiler Implementation in C. 1997, Cambridge University Press.ISBN 0-521-58653-4.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 52

Page 53: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

1 · Syntax & Semantik Weiterfuhrendes Wissen · 1.6

Der Kreis schließt sich

I Dieses Kapitel spricht (Metasprache) uber diverse Objektsprachen, z.B.Regulare Ausdrucke (cf. Seite 31), und Grammatiken (cf. Seite 34).• Diese wurden wiederum als Metasprachen verwendet, um z.B. ArithEx und

BoolEx zu beschreiben.• Leicht kann man eine Grammatik fur Regulare Ausdrucke angeben.

I Manchmal haben wir Formeln verwendet statt sie zu beschreiben.• So haben wir etwa Mengenarithmetik (∪, ∈ und {·}) verwendet.• Die Struktur verstehen Sie anhand von Konventionen und Klammern.• Die Bedeutung verstehen Sie aus der Bedeutung der Teilausdrucke.

I In der Definition von Regularen Ausdrucken (cf. Seite 31) haben wir dieMetavariablen x , r und s verwendet. Der Absatz “Notation” dort isteine Anwendung des Abschnitts Klammern und Konvention, cf. Seite 39.

I Fur eine Struktur sind verschiedene Syntaxen denkbar: Wir haben z.B.die besonders kompakte EBNF fur Grammatiken eingefuhrt (cf. Seite 52).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 53

Page 54: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2Funktionale Programmierung

Aunt Agatha: Well, James, what programming language are you studying in this termat university?

James: Haskell.

Agatha: Is that a procedural language, like Pascal?

James: No.

Agatha: Is it object-oriented, like Java or C++?

James: No.

Agatha: What then?

James: Haskell is a fully higher-order purely functional language withnon-strict semantics and polymorphic static typing.

Agatha: Oh. 〈Pause〉 More tea, James?

—Originally due to Richard Bird.

Page 55: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung

Programmieren (nur) mit Funktionen

I (Fast) jede Programmiersprache kennt Funktionen (und manchmalProzeduren), die man mit geeigneten Parametern aufrufen kann, umirgendetwas zu berechnen.

I Funktionale Programmierung besteht nur aus der Definition und demAnwenden von Funktionen.

Beispiel Funktionen in der Mathematik, am Bsp. der Fakultatsfunktion

Definition: sei fact eine Funktion fact : N→ N mitfact 0 = 1 und fact n = n · fact (n − 1).

Anwendung: fact 4 = 24, fact 6 = 720.

I Aus Programmiersprachensicht handelt es sich bei “fact : N→ N” umeine Typdeklaration – fact ist ein Objekt eines Funktionstyps (N→ N).

I Eine Besonderheit von funktionaler Programmierung ist, dass Funktionen“first class objects” sind.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 55

Page 56: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung

“First Class Objects”—Higher-Order Functions

Was meinen wir mit “Funktionen sind first class objects?”

First class objects konnen z.B.

I an Variablen gebunden werden,

I als Argument an Funktionen ubergeben werden,

I als Ergebnis von Funktionen zuruckgegeben werden,

I in Datenstrukturen aufgenommen werden.

Intuition: So wie in der Arithmetik die Operatoren +, ×, etc. auf Zahlenoperieren, so operieren ◦ (Komposition), $ (Applikation), etc. aufFunktionen. Der Trick: ◦ und $ sind selbst ebenfalls Funktionen.

Echter Mehrwert im Vgl. zur Arithmetik: viel starkere Orthogonalitat derSprache!

Funktionen, die Funktionen als Argumente/Resultate haben, nennt manauch Funktionen hoherer Ordnung (higher-order functions).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 56

Page 57: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung

Programmieren mit Termersetzung

In Haskell, und auch sonst meist,schreibt man fur “Objekt a istvom Typ b” i.d.R. a :: b,ansonsten liest sich Haskell hierwie Mathematik. Klammern umFunktionsargumente lassen wirweg, wenn das eindeutig ist.

1 fact :: Integer -> Integer

2 fact 0 = 1

3 fact n = n * fact (n-1)

Die Auswertung einerFunktionsanwendung kann miteinfacher Textersetzunggeschehen:

fact 3_

3 ∗ fact (3− 1)_

3 ∗ fact 2_

3 ∗ 2 ∗ fact (2− 1)_

3 ∗ 2 ∗ fact 1_

3 ∗ 2 ∗ 1 ∗ fact (1− 1)_

3 ∗ 2 ∗ 1 ∗ fact 0_

3 ∗ 2 ∗ 1 ∗ 1_∗

6

Damit das wirklich so einfach funktioniert, mussen eine Reihe vonVoraussetzungen erfullt sein. Die wichtigste ist die sog. ReferenzielleTransparenz (cf. Seite 182).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 57

Page 58: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung

Auswertung mit einfacher Textersetzung?

Bei genauerer Betrachtung ergibt sich schnell eine Reihe von Fragen, z.B.

I In der Mathematik ist 2 · f n ≡ f n + f n —Hier auch?

I Auch wenn f Seiteneffekte hatte?

I Wie wird der nachste zu ersetzende Term bestimmt?

I Spielt diese Auswahl uberhaupt eine Rolle?

I Gibt es unendliche Ersetzungsfolgen?

I ...

⇒ Zur Beantwortung solcher und ahnlicher Fragen dient u.a. der λ-Kalkul.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 58

Page 59: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung

The Taste of Functional Programming (FP)

I A programming language is a medium for expressing ideas (not to get acomputer perform operations). Thus programs must be written for peopleto read, and only incidentally for machines to execute.

I Using FP, we restrict or limit not what we program, but only thenotation for our program descriptions.

I Large programs grow from small ones – idioms. Develop an arsenal ofidioms of whose correctness we are convinced (or whose correctness wehave proven). Combining idioms is crucial.

I It is better to have 100 functions operate on one data structure than 10functions on 10 data structures.

— Alan J. Perlis

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 59

Page 60: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung

FP in the real world

I Die Versionsverwaltung darcs ist in Haskell geschrieben.http://darcs.net/

I xmonad ist ein dynamisch teilender X11 Window Manager.http://xmonad.org/

I Pugs, die erste Implementation von Perl 6, wurde in Haskellgeschrieben. https://github.com/perl6/Pugs.hs

I Andere moderne Programmiersprachen bieten oft funktionale Aspekte:

Erlang http://www.erlang.org/OCaml http://caml.inria.fr/ocaml/

Scala http://www.scala-lang.org/Python http://www.python.org/

Java Script Douglas Crockford. JavaScript: The Good Parts.http://javascript.crockford.com/.

...I Mehr auf Philip Wadler’s Hompage...

http://homepages.inf.ed.ac.uk/wadler/realworld/

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 60

Page 61: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Funktionale vs. Imperative Programmierung · 2.1

2.1 Funktionale vs. Imperative Programmierung

Programme einer funktionalen Programmiersprache (functionalprogramming language, FPL) bestehen ausschließlich ausFunktionsdefinitionen und Funktionsaufrufen.

Die Bausteine der Funktionsdefinitionen sind dabei

I der Aufruf weiterer vom Programmierer definierter Funktionen und

I der Aufruf elementarer Funktionen (und Operatoren), die schon in derFPL definiert sind.

Die Anwendung (application) einer Funktion f auf ein Argument e ist daszentrale Konzept in FPLs und wird daher standardmaßig einfach durchNebeneinanderschreiben (Juxtaposition) notiert:

f e

Funktionale Programme werden ausschließlich durch das Zusammensetzenvon Funktionen konstruiert.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 61

Page 62: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Funktionale vs. Imperative Programmierung · 2.1

Funktionale PL Imperative PLProgrammkonstruktion:Applikation und Komposition

Programmkonstruktion:Sequenzen von Anweisungen

Operational:Funktionsaufruf, Ersetzung vonAusdrucken

Operational:Zustandsanderungen (Seiteneffekte)

Formale Semantik:λ-Kalkul (cf. spater)

Formale Semantik:schwierig (z.B. denotationell)

~

FPLs bieten konsequenterweise folgende Konzepte nicht:I Sequenzoperatoren fur Anweisungen (‘;’ in Pascal oder C)

• Programme werden durch Funktionskomposition zusammengesetzt,• eine explizite Reihung von Anweisungen existiert nicht.

I Zustand• FPLs sind “zustandslos” und bieten daher keine anderbaren Variablen.

I Zuweisungen (‘:=’ in Pascal, ‘=’ in C/Java)• Berechnungen in FPLs geschehen allein durch Auswertung von Funktionen,

nicht durch Manipulation des Maschinenzustandes bzw. -speichers.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 62

Page 63: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Funktionale vs. Imperative Programmierung · 2.1

Beispiel Eine Funktion, die testet, ob eine Zahl n eine Primzahl ist.

1○ Ist die Menge der Teiler (factors) von n leer, so ist n prim.

2○ Die Teiler von n sind alle Zahlen x von 2 bis n− 1, die n ohne Rest teilen.

I Diese Beschreibung der Eigenschaften einer Primzahl konnte man ingewohnter mathematischer Notation z.B. so aufschreiben:

isPrime n ⇔ factors n = ∅ ,

wobei factors n = {x | x ∈ [2, n − 1]N ∧ n mod x = 0}.I Oder direkt als funktionales Programm (hier: Haskell)

1 isPrime :: Integer -> Bool

2 isPrime n = factors n == [] -- 1○3 where

4 factors n = [ x | x <- [2..n-1], n ‘mod‘ x == 0 ] -- 2○

• Das Programm liest sich mehr wie die deklarative Spezifikation derEigenschaften einer Primzahl als eine explizite Vorschrift, den Primzahltestauszufuhren.

• Bspw. ist eine parallele Ausfuhrung von factors nicht ausgeschlossen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 63

Page 64: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Funktionale vs. Imperative Programmierung · 2.1

Imperative Programmiersprachen sind dagegen eng mit demzugrundeliegenden von Neumann’schen Maschinenmodell verknupft,indem sie die Maschinenarchitektur sehr direkt abstrahieren:

I der Programmzahler (PC) der CPU arbeitet Anweisung nachAnweisung sequentiell ab.• Der Programmierer hat seine Anweisungen also explizit aufzureihen und

Wiederholungen/Sprunge zu codieren.

I der Speicher der Maschine dient zur Zustandsprotokollierung• Der Zustand eines Algorithmus muss durch Variablenzuweisung bzw.

-auslesen explizit kontrolliert werden.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 64

Page 65: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Funktionale vs. Imperative Programmierung · 2.1

I Zusatzlich zur Losung seines Problemes hat der Programmierer einerimperativen PL die Aufgabe, obige Punkte korrekt zu spezifizieren.

I Imperative Programme

• sind oft langer als ihre FPL-Aquivalente,I Aktualisierung und Kontrolle des Zustands sind explizit zu codieren.

• sind oft schwieriger zu verstehen,I Eigentliche Problemlosung und Kontrolle der von Neumann-Maschine werden

vermischt.

• sind nur mittels komplexer Methoden auf Korrektheit zu uberprufen.I Bedeutung jedes Programmteils immer von Zustand des gesamten Speichers und

Anderungen auf diesem abhangig.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 65

Page 66: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Funktionale vs. Imperative Programmierung · 2.1

Beispiel Primzahltest in PASCAL

1 function isPrime (n : integer) : boolean;

2

3 var m : integer;

4 found_factor : boolean;

5

6 begin

7 m := 2;

8 found_factor := false;

9

10 while (m <= n-1) and (not found_factor) do

11 if (n mod m) = 0

12 then found_factor := true

13 else m := m + 1;

14

15 isPrime := not found_factor

16 end; { isPrime }

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 66

Page 67: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Funktionale vs. Imperative Programmierung · 2.1

Beobachtungen: imperative Programmierung

I Das Programm kontrolliert die Maschine durch expliziteSchleifenanweisungen (while, for), bedingte Anweisungen(if · then · else) und Sequenzierung (‘;’) von Anweisungen. DieAuswertungsfolge ist explizit festgelegt.

I Das ist das Hauptmerkmal des imperativen Stils.

I Die eigentliche Berechnung des Ergebnisses erfolgt “als Seiteneffekt” aufden Zustandsvariablen (m, found_factor).

I Die Variablen dienen gleichzeitig• zur Kontrolle der Maschine (m, found_factor) und• zur Protokollierung des (Zwischen-) Ergebnisses des eigentlichen Problems

(found_factor).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 67

Page 68: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Funktionale vs. Imperative Programmierung · 2.1

“Geringes” Abstraktionsniveau imperativer Programmierung

Andere Konzepte imperativer PLs bieten noch weitergehenden direktenZugriff auf die Maschine:I Arrays und Indexzugriff (A[i])

• Modelliert direkt den linearen Speicher der Maschine sowie indizierendeAdressierungsmodi der CPU.

I Pointer und Dereferenzierung• Modellieren 1:1 die indirekten Adressierungsmodi der CPU.

I explizite (De-)Allokation von Speicher (malloc, free, new)• Der Speicher wird eigenverantwortlich als Resource verwaltet.

I Sprunganweisungen (goto)• Direkte Manipulation des PC.

I ...

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 68

Page 69: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Ausfuhrung funktionaler Programme · 2.2

2.2 Ausfuhrung funktionaler Programme

Funktionale Programme berechnen ihre Ergebnisse allein durch dieErsetzung von Funktionsaufrufen durch Funktionsergebnisse (s. oben).Dieser Ersetzungsvorgang ist so zentral, dass wir dafur das Zeichen “_”(reduces to) reservieren.

Beispiellength [0, 2*2, fact 100] _ 3

1. Die Reihenfolge der Ersetzungen wird durch die Programme nichtspezifiziert, insbesondere konnen mehrere Ersetzungen parallel erfolgen,

2. und ein Funktionsaufruf kann jederzeit durch sein Ergebnis ersetztwerden, ohne die Bedeutung des Programmes zu andern (referenzielleTransparenz).

Frage: Gilt 2. nicht auch fur imperative PLs?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 69

Page 70: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Ausfuhrung funktionaler Programme · 2.2

Konstruktion von Funktionen

Beispiel Die Mathematik definiert eine Funktion f als eine Menge vongeordneten Paaren (x , y). Ob diese Menge explizit (durch eine Maschine)konstruierbar ist, ist hierbei nicht relevant.

Die Funktion f mit

f x =

{1 wenn x irrational ist,

0 sonst.

ist auf einem Rechner aufgrund der endlichen und daher ungenauenReprasentation von irrationalen Zahlen nicht implementierbar.Im Gegensatz zur Mathematik benotigen FPLs einen konstruktivenFunktionsbegriff.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 70

Page 71: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Ausfuhrung funktionaler Programme · 2.2

λ-Notation

Der λ-Kalkul (s. nachstes Kapitel) stellt eine Notation zur Verfugung, mitder Funktionsobjekte dargestellt werden konnen.

I “Funktion f : N→ N mit f n = n2” lesen wir als• Deklaration einer Variablen f vom Typ N→ N und• Definition des Funktionsrumpfes f n = n2.

Also ist genau genommen f der Name der Funktion(-svariablen), nichtdie Funktion selbst. Meist definieren wir in der Mathematik Funktionennur zusammen mit einem Namen.

I Jetzt wollen wir “anonyme Funktionen”, oder “die Funktion selbst”auch irgendwie aufschreiben konnen, so dass sie “first class objects”werden.

I Dazu liefert uns der λ-Kalkul das Handwerkszeug.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 71

Page 72: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Ausfuhrung funktionaler Programme · 2.2

λ-Abstraktion

Funktionen werden durch die λ-Abstraktion definiert. Beispiel:

λx︸︷︷︸ . (+ x x)︸ ︷︷ ︸formaler Parameter x Funktionsrumpf

Applikation wird dann uber Termersetzung (_) formalisiert. Beispiel:

(λ x .(+ x x)) 3 _ (+ 3 3) _ 6

I Durch λ gebundene Vorkommen von x im Rumpf werden durch aktuellenParameter 3 ersetzt.

I Ersetzungsregeln dieser Art bilden allein das operationale Modell allerFPLs.

Obacht Die λ-Notation kennt keine (binaren) Operatoren, nur Funktionen(in Prafix-Notation), daher “+ x x” statt “x + x”.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 72

Page 73: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Ausfuhrung funktionaler Programme · 2.2

Graphische Darstellung

I Die FPL-Gemeinde hat bis heute ausgefeilte Techniken entwickelt, um dieOperation _ effizient zu unterstutzen.

I Moderne FPL-Compiler erzeugen fast ausschließlich eine interneGraph-Reprasentation des Programmes, die mittels (paralleler)Graph-Reduktion die Termersetzung via _ nachbildet (sog.“G-Machines”).

Beispiel Sei f = λx . (∗ (+ x 1) (− x 1)).Dann wird der Ausdruck f 4 wie folgt reduziert:

f

4

_

+

4 1

4 1

_∗

5 3

_ 15

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 73

Page 74: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Ausfuhrung funktionaler Programme · 2.2

I Da die Applikation fur FPLs so zentral ist, wird eineGraph-Reprasentation gewahlt bei der als innere Knoten (fast) nur dieApplikation @ vorkommt.

I Wir werden diese Form spater (cf. Seite 89) vertiefen, und ausschließlichverwenden.

Beispiel f x wird dann zu@

f x

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 74

Page 75: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Ausfuhrung funktionaler Programme · 2.2

Beobachtungen

I Ausfuhrung eines funktionalen Programmes = Auswertung einesAusdrucks.

I Die Auswertung geschieht durch simple Reduktionsschritte(Graph-Reduktion).

I Reduktionen konnen in beliebiger Reihenfolge, auch parallel, ausgefuhrtwerden. (Reduktionen sind unabhangig voneinander, Seiteneffekteexistieren nicht)

I Die Auswertung ist komplett, wenn keine Reduktion mehr moglich ist(Normalform erreicht).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 75

Page 76: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Ausfuhrung funktionaler Programme · 2.2

Performance-Uberlegungen

I Exotische Architekturen, die die Reduktion _ auf Maschinen-Ebeneunterstutzten (z.B. LISP-Maschinen von Symbolics) konnten sich nichtdurchsetzen.

I Compiler fur imperative PLs erzeugen derzeit meist effizienterenMaschinen-Code:• die maschinennahen Konzepte der imperativen PLs sind direkter auf die

klassischen von Neumann-Maschinen abbildbar.• Fur parallele Maschinen-Architekturen ist dies jedoch nicht unbedingt der Fall.

I Performance ist nicht alles:• Lesbarkeit: ggf. spezielle Syntax fur eine Domane: XQuery.• Beweisbarkeit: Wie einfach ist es formal uber Programme zu argumentieren?• Prototyping: Schnell ein abstraktes Modell ausprogrammieren.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 76

Page 77: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Ausfuhrung funktionaler Programme · 2.2

Beispiel Imperative Vektortransformation(hier in PASCAL notiert) uberspezifiziert dieLosung durch explizite Iteration (bzgl. i).

1 for i := 1 to n do

2 A[i] := transform(A[i]);

I Ein vektorisierender PASCAL-Compiler hat nun die schwierige (oftunmogliche) Aufgabe, zu beweisen, dass die Funktion transform keineSeiteneffekte besitzt, um die Transformation parallelisieren zu konnen.Die inherente Parallelitat wird durch die Iteration verdeckt und mussnachtraglich wiederentdeckt werden.

I Das aquivalente funktionale Programm map transform A spezifiziertkeine explizite Iteration und lasst dem Compiler alleOptimierungsmoglichkeiten.

I “Parallele imperative Sprachen” mitentsprechenden Spracherweiterungenerlauben dem Programmierer die expliziteAngabe von Parallelisierungsmoglichkeiten.

1 for i := 1 to n do in parallel

2 A[i] := transform(A[i]);

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 77

Page 78: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Ausfuhrung funktionaler Programme · 2.2

Strikte vs. nicht-strikte Auswertung

Wird im Graphen@

f x

erst der rechte oder der linke Zweig reduziert?

rechts Strikte Auswertung. Die weitaus meisten PLs reduzieren dasArgument x bevor die Definition von f verwendet und weiter reduziertwird.

links Nicht-strikte Auswertung. Die Expansion der Definition von f bevordas Argument x ausgewertet wird kann unnotige Berechnungenersparen: Ein Argument wird erst dann ausgewertet, wenn eineFunktion tatsachlich auf das Argument zugreifen muss.

Beispiel Nicht-strikte Funktionen: (genaue Definition spater)

k x y = x

pos f x =

{0 falls x < 0

f x sonst

Hingegen ist der +-Operator strikt in beiden Argumenten.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 78

Page 79: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Ausfuhrung funktionaler Programme · 2.2

Nicht-strikte Auswertung eroffnet neue Wege zur Strukturierung vonProgrammen.

I Programme konnen auf potentiell unendlich großen Datenstrukturen(etwa Listen) operieren. Nicht-strikte Auswertung inspiziert dieunendliche Struktur nur soweit wie dies zur Berechnung desErgebnisses notwendig ist (also nur einen endlichen Teil).

Beispiel Das “Sieb des Eratosthenes” kann einfach als Filter auf einempotentiell unendlichen Strom von naturlichen Zahlen ab 2 (Haskell: [2..])definiert werden:

1 primes :: [Integer]

2 primes = sieve [2..]

3

4 sieve (x:xs) = x : sieve [ y | y <- xs, y ‘mod‘ x > 0 ]

Solange nur jeweils eine endliche Anzahl von Primzahlen inspiziert wird(etwa durch den Aufruf take n primes) terminiert das Programm:

1 > take 10 primes

2 [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 79

Page 80: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Ausfuhrung funktionaler Programme · 2.2

I Programme konnen durch Funktionskomposition klar strukturiert undaus einfachen Funktionselementen zusammengesetzt werden.

I Bei nicht-strikter Auswertung werden in der Komposition

g (f x)

g und f synchronisiert ausgefuhrt: f wird nur dann aufgerufen, wenn gdies verlangt; f konsumiert sein Argument x nur soweit, wie dies zurBeantwortung von gs Anfrage notwendig ist.

Beispiel Ein Programm zur iterativen Wurzelberechnung kann auseinfachen Bauteilen zusammengesetzt werden:

Erinnerung: Iterative Berechnung von√x :

r0 =x

2

rn+1 = rn +x − r2

n

2 · rn

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 80

Page 81: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Ausfuhrung funktionaler Programme · 2.2

I Die Iterationsvorschrift wird durch die Funktion rn1 implementiert:

rn+1 = rn +x − r2

n

2 · rn1 rn1 rn = rn + (x - rn*rn) / (2*rn)

I Die eigentliche Iteration realisieren wir durch die Standardfunktioniterate, die mit zwei Argumenten f und r die unendliche Liste

[ r , f r , f (f r) , f (f (f r)) , f (f (f (f r))) , ...]

generiert. Startwert r0 = x/2. Beispiel mit x = 17:

1 *Main> iterate rn1 (x/2)

2 [8.5,5.25,4.244047619047619,4.124828858612169,4.123105985575862^CInterrupted.

I Es fehlt nur noch eine Funktion die entscheidet, ob die Iteration weitgenug fortgeschritten ist (die Differenz zweier aufeinanderfolgenderListenelemente ist < ε):

1 within eps (x1:x2:xs) | abs (x1-x2) < eps = x2

2 | otherwise = within eps (x2:xs)

1 *Main> within 0.0001 (iterate rn1 (x/2))

2 4.123105625617677

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 81

Page 82: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

2 · Funktionale Programmierung Ausfuhrung funktionaler Programme · 2.2

I Komposition fugt die Teile zu einer iterativen Wurzelberechnungsfunktionisqrt zusammen:

1 isqrt eps x = within eps (iterate rn1 r0)

2 where

3 r0 = x/2

4 rn1 rn = rn + (x - rn*rn) / (2*rn)

1 *Main> isqrt 0.001 17

2 4.123105625617677

3 *Main> isqrt 0.0000001 17

4 4.123105625617661

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 82

Page 83: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3Der λ-Kalkul

Page 84: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Uberblick · 3.1

3.1 Uberblick

Alonzo Churchs λ-Kalkul (ca. 1940) ist der formale Kern jederfunktionalen Programmiersprache.

Der λ-Kalkul

I ist eine einfache Sprache mit nur wenigen syntaktischen Konstruktenund simpler Semantik.

⇒ Eine Implementation des λ-Kalkuls ist leicht zu erhalten und damit eine guteBasis fur die Realisierung von FPLs.

I ist eine machtige Sprache. Jede berechenbare Funktion kann imλ-Kalkul dargestellt werden.

⇒ Alle Konzepte, auch die moderner Sprachen, lassen sich auf den λ-Kalkulabbilden.

⇒ Im Prinzip konnten wir einen Compiler fur eine FPL erhalten, indem wir sieauf den λ-Kalkul abbilden und dessen Implementation nutzen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 84

Page 85: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Uberblick · 3.1

FPL ←→ λ-Kalkul

Funktionales Programm ≡ Ausdruck des λ-KalkulsAusfuhrung des Programms ≡ Auswertung durch Reduktion

Auswertung Primitiver Algorithmus:

1. Wahle nachsten zu reduzierenden Teilausdruck e (Redex, reducibleexpression).

2. Ersetze Redex e durch Reduktionsergebnis e ′.

3. Stop, wenn Normalform erreicht. Sonst zuruck zu 1○.

Notation Schreibe fur Schritt 2○ ab jetzt: e _ e ′

(sprich: e wird zu e ′ reduziert, e reduces to e ′)

Auswertungsverfahren (insbesondere die Schritte 1○ und 3○) untersuchenwir spater genauer.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 85

Page 86: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Uberblick · 3.1

Beispiel Auswertung von (+ (× 5 6) (× 8 3)) durch Reduktion:

(+ (× 5 6) (× 8 3))

_ Zwei Redexe: (× 5 6) und (× 8 3). Wahle ersten (beliebig).

Reduktion: (× 5 6) _ 30.

(+ 30 (× 8 3))

_ Normalform? Nein, ≥ 1 Redex verbleibt. Wahle einzigen

Redex (× 8 3). Reduktion: (× 8 3) _ 24.

(+ 30 24)

_ Normalform? Nein, ≥ 1 Redex verbleibt. Wahle einzigen

Redex (+ 30 24). Reduktion: (+ 30 24) _ 54.

54

Normalform? Ja, kein Redex verbleibt. Stop.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 86

Page 87: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Currying · 3.2

3.2 Currying

Im λ-Kalkul genugt es Funktionen mit nur einem Argument zubetrachten, ebenso in den meisten FPLs.

Beispiel Zweistellige Funktionen:

I Wir schreiben in der Mathematik ublicherweise etwa

f :: N× N→ N mit f (a, b) = a + b ,

und lesen dies als: “die Funktion f hat zwei Argumente”.(oder auch: ein zusammengesetztes Argument, namlich ein Tupel zweier Zahlen)

I Im FPL-Kontext schreiben wir eher

f :: N→ N→ N mit f a b = + a b ,

was bedeutet: f ist eine Funktion mit einem Argument (vom Typ N), dieeine (anonyme) Funktion zuruckgibt (vom Typ N→ N).Wendet man diese auf eine zweite Zahl an, so kommt wieder eine Zahl heraus.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 87

Page 88: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Currying · 3.2

Genauer mussten wir den Typ der Funktion f also so notieren:

f :: N→ (N→ N)

und damit die Funktionsanwendung als: (f a) b.

I Als Konvention vereinbart man• Links-Assoziativitat der Funktionsanwendung und• Rechts-Assoziativitat des Pfeils,

und lasst die Klammern in beiden Fallen weg (sofern nicht im Kontextnotwendig).

I Diese Technik nennt man Currying16.

I Sie ermoglicht auch die partielle Anwendung (partial application). ImBeispiel ist auch “f a” ein wohldefinierter Ausdruck, bei dem dieFunktion f nur partiell angewendet wurde.

16Obwohl das Verfahren von Moses Schonfinkel erfunden und von Gottlob Frege vorausgedacht

wurde, ist es nach Haskell Brooks Curry benannt, der das Verfahren letztlich umfangreich theore-

tisch ausgearbeitet hat.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 88

Page 89: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Currying · 3.2

Graph-Reprasentation

I Mit Currying macht auch die bereits angedeutete Reprasentation mit derApplikation (@) als innere Knoten Sinn (cf. Seite 74).

(spater werden wir noch ‘λ‘ als inneren Knoten hinzufugen)

Beispiel λ-Ausdrucke und ihr AST17

I Jf xK =@

f x

I Jf a bK =

@

@

f a

b

I Jf x (g y z)K =

@

@

f x

@

@

g y

z

17Abstract Syntax Tree, cf. Seite 27Stefan Klinger · DBIS Informatik 2 · Sommer 2016 89

Page 90: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Currying · 3.2

Funktionen hoherer Ordnung

Currying ist ein Beispiel fur die Verwendung von Funktionen hohererOrdnung: Funktionen konnen Funktionen als Argumente und/oderResultate haben.

Beispiel map — wende eine Funktion auf alle Elemente einer Menge18 an.

map :: (A→ B)→ P A→ P B

map f S = { f x | x ∈ S }

Anwendung: map malZwei {1, 2, 3, 4, 5} _ {2, 4, 6, 8, 10}

I Die Eleganz funktionaler Programme wird u.a. durch “higher orderfunctions” erreicht.

18Dabei bezeichnet P A die Potenzmenge von A, also die Menge aller Teilmengen von A.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 90

Page 91: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Syntax des λ-Kalkuls · 3.3

3.3 Syntax des λ-Kalkuls

I Funktionsanwendung: Juxtaposition von Funktion und Argument,notiert in Prafix-Form:

f x

I Curried functions: Mittels Currying wird jede Funktion als Funktioneines einzigen Arguments dargestellt. Beispiel:

(+ x) y

I Vereinbarung: Funktionsanwendung ist links-assoziativ. Schreibe daherauch kurzer:

+ x y

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 91

Page 92: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Syntax des λ-Kalkuls · 3.3

Konstanten und vordefinierte Funktionen

I Der Kern des λ-Kalkuls bietet keine Konstanten (wie 42, "foo", Trueoder primitive Funktionen wie +, ×, if).

I In dieser Vorlesung verwenden wir meist einen um Primitive undentsprechende Reduktionsregeln erweiterten λ-Kalkul.

Beispiel Reduktion einiger vordefinierter Funktionen(spater: δ-Reduktion _

δ):

+ x y _ x � y

× x y _ x � y

if True e f _ eif False e f _ fand False e _ False

and True e _ e

(Operationen in � seien direkt auf der Zielmaschine ausfuhrbar, wenn dieArgumente x und y zuvor bis zur Normalform reduziert wurden)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 92

Page 93: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Syntax des λ-Kalkuls · 3.3

λ-Abstraktion

Mit der sog. λ-Abstraktion werden im λ-Kalkul neue Funktionen definiert:

λx . e

In dieser λ-Abstraktion ist x der formale Parameter, der imFunktionskorper e zur Definition der Funktion benutzt werden kann(sprich: x ist in e gebunden). Der Punkt ‘.’ trennt x und e.

Beispiel Funktion, die ihr Argument inkrementiert:

λx . (+ x 1)

Maximumsfunktion:

λx . (λy . (if (< x y) y x))

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 93

Page 94: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Syntax des λ-Kalkuls · 3.3

Die Grammatik des λ-Kalkuls

Definition Grammatik des um Konstanten erweiterten λ-Kalkuls

Expr → Const Konstanten, z.B. ‘c‘, 42, +| Var Variablen, z.B. x, f, bar| (Expr Expr) Applikation (Juxtaposition)| (λVar .Expr) λ-Abstraktion

Notation (cf. Seite 39)

I Treten keine Mehrdeutigkeiten auf konnen Klammern (·) weggelassenwerden.

I Applikation ist links-assoziativ.

I Der Wirkungsbereich der λ-Abstraktion erstreckt sich bis zum Ende deslangsten gultigen Terms.

f ( λx .

inneres λ︷ ︸︸ ︷λy . + 2 (× x y)︸ ︷︷ ︸

außeres λ

) 42

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 94

Page 95: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Syntax des λ-Kalkuls · 3.3

Beispiele

I f (g x) 6≡ f g x ≡ (f g) x

I λx . (f x) ≡ λx . f x 6≡ (λx . f ) x

I ((λx . ((+ x) 1)) 4) ≡ (λx . + x 1) 4

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 95

Page 96: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Operationale Semantik des λ-Kalkuls · 3.4

3.4 Operationale Semantik des λ-Kalkuls

Um den λ-Ausdruck(λx . + x y) 4

auszuwerten

I wird der nicht bekannte “globale” Wert der Variablen y benotigt (wirbrauchen einen Kontext der y liefert), andererseits

I ist der Wert des Parameters x im Funktionskorper (+ x y) durch dasArgument 4 festgelegt.

Man sagt: Innerhalb der λ-Abstraktion

I ist der Parameter x durch das λ gebunden, wahrend

I die Variable y frei ist.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 96

Page 97: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Operationale Semantik des λ-Kalkuls · 3.4

Definition Freie und gebundene Vorkommen von Variablen

Seien x , y , v Variablen; c Konstanten; e, e ′ beliebige λ-Ausdrucke19.

Freies Vorkommen einer Variablen x :

x ist frei in v ⇐⇒ x = v

x ist frei in (e e ′) ⇐⇒ x ist frei in e oder x ist frei in e ′

x ist frei in (λy .e) ⇐⇒ x 6= y und x ist frei in e

In einem Ausdruck der aus einer einzigen Konstanten c besteht, ist xniemals frei.

Gebundenes Vorkommen einer Variablen x :

x ist gebunden in (e e ′) ⇐⇒ x ist gebunden in e oder in e ′

x ist gebunden in (λy .e) ⇐⇒ x = y oder x ist gebunden in e

In einem Ausdruck der aus einer einzigen Variablen v bzw. Konstanten cbesteht, ist x nie gebunden.

19Obacht: Das sind sind Metavariablen, z.B. steht x fur irgend eine Variable, cf. Seite 48.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 97

Page 98: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Operationale Semantik des λ-Kalkuls · 3.4

Generell hangt der Wert eines Ausdrucks nur von seinen freien Variablen ab.

Beispiel In der λ-Abstraktion

λx . + ((λy . × y z) 7) x

sind die Variablen x und y gebunden, z jedoch frei.

~

Vorsicht! Bindung/Freiheit muss fur jedes einzelne Auftreten einesNamens entschieden werden. Ein Variablenname kann innerhalb einesAusdrucks gebunden und frei auftreten.

Beispiel Hier kommt x sowohl gebunden, als auch frei vor:

+ xfrei

((λx . + xgebunden

1) 4)

Gleich werden wir sehen dass es sich um verschiedene Variablen handelt,die zufallig den gleichen Namen haben (cf. Seite 102).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 98

Page 99: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Operationale Semantik des λ-Kalkuls · 3.4

β-Reduktion

Die β-Reduktion definiert, wie eine λ-Abstraktion auf ein Argumentangewandt wird.

Definition β-Reduktion _β

Vorlaufig, cf. Seite 109

Seien x Variable; e, m λ-Ausdrucke. Die Funktionsanwendung

(λx . e) m

wird reduziert zu

I einer Kopie des Funktionsrumpfes e,

I in der die (dann) freien Vorkommen von x durch m ersetzt wurden.

Beispiel(λx . + x 1) 4 _

β+ 4 1 _

δ5

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 99

Page 100: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Operationale Semantik des λ-Kalkuls · 3.4

Beispiele

I Der formale Parameter kann mehrfach im Funktionsrumpf auftreten:

(λx . + x x) 5 _β

+ 5 5 _δ

10

I Der formale Parameter muss nicht im Funktionsrumpf auftreten:

(λx . 3) 5 _β

3

I In einem Funktionsrumpf kann eine weitere λ-Abstraktion enthalten sein(Currying cf. Seite 87):

(λx . (λy . × y x)) 4 5_β (λy . × y 4) 5_β × 5 4_δ 20

Notation Schreiben abkurzend λx y . e statt λx . λy . e .

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 100

Page 101: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Operationale Semantik des λ-Kalkuls · 3.4

Beispiel Funktionen konnenproblemlos als Argumenteubergeben werden:

(λf . f 3) (λx . + x 1)_β (λx . + x 1) 3_β + 3 1_δ 4

Wichtig Bei β-Reduktion werden genau die in der Kopie desFunktionsrumpfes freien Vorkommen des formalen Parameters ersetzt:

(λx .(λx . + (− x 1)

)x 3) 9

_β (λx .+ (− x 1)) 9 3_β + (− 9 1) 3

∗11

Das unterstrichene Vorkommen vonx ist durch die innere λ-Abstraktiongebunden und wird daher bei derersten β-Reduktion nicht ersetzt.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 101

Page 102: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Operationale Semantik des λ-Kalkuls · 3.4

α-Konversion

Erinnerung Generell hangt der Wert eines Ausdrucks nur von seinenfreien Variablen ab. —cf. Seite 98

Im Umkehrschluss heißt das:Die Bedeutung eines λ-Ausdrucks andert sich nicht, wenn wir gebundeneVariablen konsistent umbenennen, d.h. wenn wir alle durch das gleiche λgebundenen Vorkommen durch den gleichen neuen Namen ersetzen:

(λx . × x 2) ]α

(λy . × y 2)

I Man sagt auch: Diese Ausdrucke sind gleich bis auf Umbenennen, odergleich modulo α-Konversion.

I Manchmal ist diese α-Konversion unerlaßlich, um Namenskollisionenund damit fehlerhafte Reduktionen (sog. “name capture”) zu vermeiden.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 102

Page 103: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Operationale Semantik des λ-Kalkuls · 3.4

Name Capture

Beispiel Betrachten wir den λ-Ausdruck(λy . (λx y . + x y) y 3

)5

und zwei verschiedene Reihenfolgen bei der Auswertung:(λy . (λx y . + x y) y 3

)5

zuerst außeren Redex

(λx y . + x y) 5 3_β (λy . + 5 y) 3_β + 5 3_δ 8

(λy . (λx y . + x y) y 3

)5

zuerst inneren Redex(λy . (λy . + y y) 3

)5

_β (λy . + y y) 3_β + 3 3_δ 6 — Falsch!

Frage Was ist schief gegangen?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 103

Page 104: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Operationale Semantik des λ-Kalkuls · 3.4

(λy . (λx y . + x y) y 3

)5

_β(λy . (λy . + y y) 3

)5

I Das zunachst durch das außere λgebundene y ist nun falsch durchdas innere λ gebunden (captured).

Losung Umbenennung durch α-Konversion hilft hier:(λy . (λx y . + x y) y 3

)5

Ersetze λy durch λz(λy . (λx z . + x z) y 3

)5

_β(λy . (λz . + y z) 3

)5

I Ersetzen die durch das innere λgebundenen y konsistent durchneue Variable z .

I Das y wird jetzt von λz nichtmehr eingefangen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 104

Page 105: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Operationale Semantik des λ-Kalkuls · 3.4

Noch ein Beispiel Unter dem Namen twice sei folgende Funktiondefiniert :

twice = λf x . f (f x)

Wir verfolgen jetzt die Reduktion des Ausdrucks twice twice mittelsβ-Reduktion.

twice twice=

(λf x . f (f x)) twice_β λx . twice (twice x)_β λx . twice (twice x︸ ︷︷ ︸

2○)

︸ ︷︷ ︸1○

Es entstehen die Redexe 1○ und 2○.Wir wahlen 2○ beliebig,

dann:

λx . twice (

2○︷ ︸︸ ︷twice x)

=λx . twice ((λf x . f (f x)) x)

_β λx . twice (λx . x (x x))

Falsch! Die x sind nun durch dieinnere λ-Abstraktion gebunden(captured). Umbenennung mittelsα-Konversion hilft hier...

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 105

Page 106: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Operationale Semantik des λ-Kalkuls · 3.4

Es ist notig die Variable der innerenBindung umzubenennen, bevor dieErsetzung stattfindet.

λx . twice (

2○︷ ︸︸ ︷twice x)

=λx . twice ((λf x . f (f x)) x)

]α λx . twice ((λf y . f (f y)) x)_β λx . twice (λy . x (x y))

~

Obacht An dieser Stelle erkennt man auch, dass es sich bei den x in

λx . twice ((λf x . f (f x)) x)

um verschiedene Variablen handelt, die den gleichen Namen tragen.

I Sie unterscheiden sich durch das λ welches sie bindet.

I Jede Variable ist entweder frei oder durch genau ein λ gebunden.

I α-Konversion einer Variablen kann dies sichtbar machen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 106

Page 107: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Operationale Semantik des λ-Kalkuls · 3.4

Die Einsetzung ist so zentral, dass wir ihr eine eigene Notation spendieren:

Definition e[x�m] sprich: “m fur x in e”, oder “e mit x ersetzt durch m”

Seien x , v Variablen; c Konstante; m, e, e1, e2 beliebige λ-Ausdrucke.

c[x�m] = c

v [x�m] =

{m wenn v = x

v sonst

(e1 e2)[x�m] = e1[x�m] e2[x�m]

(λv . e)[x�m] =

λv . e wenn v = x

λv . e[x�m] wenn v 6= x , undv nicht frei in m ist

(λz . e[v�z ])[x�m] sonst, z neuer Variablenname(das ist α-Konversion)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 107

Page 108: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Operationale Semantik des λ-Kalkuls · 3.4

~

Vorsicht Einsetzen ist eine Operation der Meta-Ebene.

I Die Notation e[x�m] beschreibt eine syntaktische Veranderung, diewir am λ-Ausdruck e vornehmen.

I Diese Operation ist nicht Bestandteil eines λ-Ausdrucks!• Es ist eine Operation auf einem λ-Ausdruck.• Die Grammatik des λ-Kalkuls (cf. Seite 94) kennt den Ersetzungsoperator·[·� ·] uberhaupt nicht.

Notation Der Ersetzungsoperator ·[·� ·] bezieht sich immer auf denkurzesten voranstehenden gultigen λ-Ausdruck:

a (a b)[a�x ] = a (x b)6= x (x b)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 108

Page 109: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Operationale Semantik des λ-Kalkuls · 3.4

Zusammenfassung

Damit sind alle Regeln zum Umgang mit dem λ-Kalkul vorhanden:

Definition Operationale Semantik des λ-Kalkuls

Seien x , y Variablen; m, e beliebige λ-Ausdrucke; ∗ primitive Operation.

α-Konversion λx . e ]α

λy . e[x�y ] wenn y nicht frei in e

β-Reduktion (λx . e) m _β

e[x�m]

δ-Reduktion ∗ e _δ

� e wenn e in Normalform20

Dieses kompakte formale System ist ausreichend, um als Zielsprache fur allefunktionalen Programmiersprachen zu dienen.

I Tatsachlich ist Haskell ein syntaktisch stark angereicherter λ-Kalkul.

I Manche Sprachelemente von Haskell werden wir auf den λ-Kalkulzuruckfuhren.

20d.h. e enthalt keinen Redex; � implementiert ∗ auf der Zielmaschine.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 109

Page 110: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Anmerkungen · 3.5

3.5 Anmerkungen Namen als Abkurzungen fur Terme

Betrachten wir nochmal die Definition von Seite 105:

twice = λf x . f (f x)

I Diese Zeile ist nicht im λ-Kalkul geschrieben, denn der kennt keineZuweisung, kein =-Zeichen.

I twice ist eine Metavariable, die uns als Abkurzung fur den Termλf x . f (f x) dient.

I Obacht: Wenn man twice verwendet, dann tut man so als warenKlammern drum herum:

twice x ≡ (λf x . f (f x)) x6≡ λf x . f (f x) x

twice x meint also die Anwendung des ganzen Ausdrucks twice auf denAusdruck x , nicht die syntaktische Konkatenation der beiden.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 110

Page 111: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Anmerkungen · 3.5

Aquivalenz Wann sind λ-Ausdrucke gleich?

I Man hatte auch schreiben (und denken) konnen:

twice = λharry foo. harry (harry foo)

I Diese Erkenntnis wird rigoros angewandt: λ-Ausdrucke die bis aufα-Konversion gleich sind, werden semantisch nicht unterschieden!

• De Bruijn indices sind eine Syntax fur λ-Ausdrucke, welche keine α-Konversion benotigt.• Der SK -Kalkul verwendet gar keine Variablen, ist aber gleich machtig wie der λ-Kalkul.

I Etwas weiter gefasst ist die Aquivalenz:

Definition Aquivalenz von λ-Ausdrucken

Zwei λ-Ausdrucke e1, e2 heißen aquivalent, gdw. sie zur gleichenNormalform reduziert werden konnen, d.h.:

e1 ≡ e2 ⇔ ∃m. e1 _∗m ∧ e2 _∗m

wobei _∗ hier durchaus fur unterschiedlich viele Schritte stehen kann.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 111

Page 112: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Exkurs: Variablenbindung anderswo · 3.6

3.6 Exkurs: Variablenbindung anderswo

I Das Konzept der Variablenbindung begegnet uns auch in der Mathematikund in anderen Programmiersprachen.

∀x . 2 · x > t

n∑i=1

2 · i − 1

1 for (int i = 0; i < k; i++) {2 print(i);

3 }

Frage Was sind hier die freien Variablen? Welche sind gebunden? Wofindet die Bindung statt?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 112

Page 113: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Exkurs: Variablenbindung anderswo · 3.6

α-Konversion?

I Auch hier ist der gewahlte Name eigentlich nicht relevant (cf. Seite 102).

∀x . 2 · x > t ≡ ∀y . 2 · y > t

n∑i=1

2 · i − 1 ≡n∑

j=1

2 · j − 1

1 for (int i = 0; i < k; i++) {2 print(i);

3 }≡

1 for (int j = 0; j < k; j++) {2 print(j);

3 }

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 113

Page 114: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Exkurs: Variablenbindung anderswo · 3.6

Scoping

I Bei vielen Programmiersprachen konnen wir die Verwendungverschiedener Variablen mit dem gleichen Namen beobachten:

1 int i = 42;

2 for (int i = 0; i < 10; i++) {3 print(i); // gibt 0–9 aus4 }5 print(i); // gibt 42 aus

Die innere Variable i uberdeckt dieaußere. Innerhalb der Schleife kannauf die 42 nicht zugegriffen werden.

I Der Bereich in dem eine Variable syntaktisch verwendet werden kann,heißt Sichtbarkeitsbereich, oder Scope.

I Ob, und wo eine Variable sichtbar ist, hangt von der jeweiligenProgrammiersprache ab.• Obiger Code ware in C erlaubt, hingegen• verbietet Java diese Uberdeckung (aka. Shadowing).⇒ Scoping-Regeln der Sprache lesen!

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 114

Page 115: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Exkurs: Variablenbindung anderswo · 3.6

I Was in der Programmierung als zumindest fragwurdiger Stil gesehenwerden kann, ist in der Mathematik unublich, wenn nicht verpont:

∀x . ∃y . Px ,y ∧ ∀x . Qx ,y oder10∑i=1

(5 ·

i∑i=1

3 · i

)

(Manche sagen: Das macht keinen Sinn! — Kann aber beim Einsetzen passieren)

I Ublich ist aber die Wiederverwendung der Zahlvariablen innebeneinander stehenden Termen:

n∑i=1

(2 · i − 1) +n∑

i=0

5 · i

Tatsachlich sind das verschiedene Variablen die beide i heißen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 115

Page 116: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Ausdruckskraft des λ-Kalkuls · 3.7

3.7 Ausdruckskraft des λ-Kalkuls

Frage: Gibt es Dinge die wir nur in anderen Sprachen berechnen konnen?Was kann man wirklich mit dem λ-Kalkul ausdrucken?

Antwort: Alles was man uberhaupt mit irgendeiner Programmierspracheausdrucken kann, kann man auch im λ-Kalkul ausdrucken.

I Solche formalen Systeme (und damit den λ-Kalkul) nennt manTuring-vollstandig.

cf. Seite 190, Exkurs zum Thema Berechenbarkeit.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 116

Page 117: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Ausdruckskraft des λ-Kalkuls · 3.7

Datenstrukturen vs. Operationen

I Wir haben schon betont, dass der (reine) λ-Kalkul keine primitivenDatentypen (z.B. Integer, Boolean) kennt und auch keine“eingebauten” Operationen darauf.

I Dennoch kann man diese mit dem λ-Kalkul nachbilden. Ebenso wie mankonstruierte Datentypen mit Funktionen “nachbauen” kann.

Beispiel Darstellung von Paaren im λ-Kalkul: Wir beschreiben zunachstdie Schnittstelle des abstrakten Typs Pair.

pair :: α→ β → Pair α β (Konstruktor)

fst :: Pair α β → α (Accessor)snd :: Pair α β → β (Accessor)

und seine Eigenschaften

fst (pair a b) ≡ a snd (pair a b) ≡ b

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 117

Page 118: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Ausdruckskraft des λ-Kalkuls · 3.7

(nochmal die Eigenschaften)

fst (pair a b) ≡ a

snd (pair a b) ≡ b

... bis hierhin sieht das aus wie einealgebraische Spezifikation einesabstrakten Datentyps.

Jetzt realisieren wir das im λ-Kalkul:

pair = λx y s. s x y

fst = λp. p (λx y . x)

snd = λp. p (λx y . y)

...bleibt nur noch zu beweisen, dassdie geforderten Eigenschaften erfulltsind.

Beweis fur fst (pair a b) ≡ a:

fst (pair a b)=

(λp. p (λx y . x)) (pair a b)_β pair a b (λx y . x)=

(λx y s. s x y) a b (λx y . x)_β (λy s. s a y) b (λx y . x)_β (λs. s a b) (λx y . x)_β (λx y . x) a b_β (λy . a) b_β a

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 118

Page 119: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

3 · Der λ-Kalkul Ausdruckskraft des λ-Kalkuls · 3.7

I Ahnlich kann man das auch mit primitiven (z.B. Boolean und Integer)oder anderen konstruierten Datentypen (z.B. Listen) machen.

I Diese Technik der Reprasentation von Daten und Operatoren im λ-Kalkulnennt man Church Codierung (siehe dazu auch spater: “AlgebraischeDatentypen” sowie einige Ubungsaufgaben).

Dualitat von Daten und Operationen

... ein Beispiel dafur, dass die Unterscheidung zwischen Daten undOperationen keine scharfe, zwingende ist.

Man kann auch umgekehrt ein Programm (z.B. einen λ-Ausdruck) alsDatenobjekt betrachten und mit einem (anderen oder gar dem gleichen)Programm bearbeiten ...

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 119

Page 120: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4Haskell – Typen, Werte und einfache

Definitionen

Page 121: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Typen · 4.1

4.1 Typen

Intuitiv unterteilt man die Objekte, die man mit einer Programmiersprachemanipulieren will, in disjunkte Mengen, etwa: Zeichen, ganze Zahlen,Listen, Baume und Funktionen:

I Objekte verschiedener Mengen haben unterschiedliche Eigenschaften,(Zeichen und auch ganze Zahlen sind bspw. anzuordnen, Funktionen nicht)

I fur die Objekte verschiedener Mengen sind unterschiedlicheOperationen sinnvoll.(eine Funktion kann angewandt werden, eine ganze Zahl kann mit 0 verglichen werden,aber auf einen Wahrheitswert kann man nicht addieren, etc.)

Viele Programmiersprachen (wie auch Haskell) formalisieren dieseIntuition mittels eines Typsystems.

Typen im λ-Kalkul?

I Weder der einfache, noch der erweiterte λ-Kalkul haben ein Typsystem.

I Spater werden wir Typsystem fur den λ-Kalkul betrachten.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 121

Page 122: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Typen · 4.1

Ein Typ definiert

1. eine Menge von gleichartigen Objekten (Wertevorrat, “Domain”) und

2. Operationen, die auf diese Objekte anwendbar sind (Interface).

Einige Basis-Typen:

Objektmenge Typname Operationen (Auswahl)

Ganze Zahlen Integer +, max, <, >, ==Zeichen Char max, <, >, ==

Wahrheitswerte Bool &&, ==, notFließkommazahlen Double *, /, round

Typkonstruktoren konstruieren aus beliebigen Typen α, β neue Typen:

Objektmenge Typkonstruktor Operationen (Auswahl)

Funktionen von α nach β α→ β $, mapListen von α-Objekten [α] head, reverse, length

Paare von α, β-Objekten (α,β) fst, snd

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 122

Page 123: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Typen · 4.1

I Die Notation x :: α (x hat den Typ α) wird vom Haskell-Compilereingesetzt, um anzuzeigen, dass das Objekt x den Typ α besitzt.

I Umgekehrt konnen wir so dem Compiler anzeigen, dass x eine Instanzdes Typs α sein soll.

Beispiel2 :: Integer

’X’ :: Char

0.05 :: Double

round :: Double -> Integer

[2,3] :: [Integer]

head :: [α] -> α(’a’,(2,True)) :: (Char,(Integer,Bool))

snd :: (α,β) -> β

I Manche Typen (z.B. von snd) enthalten Typvariablen α, β, ....

I Das entspricht der Beobachtung, dass snd das zweite Element einesPaares bestimmen kann, ohne Details der gepaarten Objekte zukennen oder Operationen auf diese anzuwenden.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 123

Page 124: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Interpretation komplexer Typen · 4.2

4.2 Interpretation komplexer Typen

Beispiel Typ der Prelude-Funktion unzip :: [(α, β)]→ ([α], [β])

unzip :: ... → ... unzip ist eine Funktion...unzip :: [...] → ... ...die eine Liste...unzip :: [(α,β)] → ... ...von Paaren als Argument hat, ...unzip :: [(α, β)] → (...,...) ...und ein Paar...unzip :: [(α, β)] → ([α], [β]) ...von Listen als Ergebnis liefert, ...

...und dabei ist der Elementtyp α der ersten Liste der gleiche wie der Typder ersten Komponente der Argumentlistenpaare und derjenige der zweitenListe (also β) der gleiche wie der der zweiten Komponente derArgumentlistenpaare.

unzip [(x1, y1), ..., (xn, yn)] _ ([x1, ..., xn], [y1, ..., yn])

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 124

Page 125: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Currying und der Typkonstruktor “→” · 4.3

4.3 Currying und der Typkonstruktor “→”

Erinnerung Mittels Currying kann eine Funktion mehrerer Argumentesukzessive auf ihre Argumente angewandt werden (cf. Seite 87).

I Auch haskell verwendet Currying, und damit

I spielt Currying auch bei der Typisierung von Funktionen eine Rolle.

Beispiel Typ der Funktion (des Operators) +, bei Anwendung auf zweiArgumente vom Typ Integer, also x :: Integer, y :: Integer:

x + y ≡ ((+ x) y)

1. Der Teilausdruck (+ x) besitzt den Typ Integer→ Integer,

2. damit hat + also den Typ Integer→ (Integer→ Integer).

Vereinbarung: → ist rechts-assoziativ. Schreibe daher kurzer

(+) :: Integer→ Integer→ Integer

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 125

Page 126: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Currying und der Typkonstruktor “→” · 4.3

Haskell besitzt einen Mechanismus zur Typinferenz, der fur (fast) jedesObjekt x den zugehorigen Typ α automatisch bestimmt. Haskell ist

streng typisiert, d.h. eine Operation kann niemals auf Objekte angewandtwerden, fur die sie nicht definiert wurde.

statisch typisiert, d.h. schon zur Ubersetzungszeit und nicht erst wahrenddes Programmlaufs wird sichergestellt, dass Programme keine Typfehlerenthalten.

⇒ Der Interpreter oder Compiler weist inkorrekt typisierte Ausdrucke sofortzuruck.

Beispiel Typische Typfehlermeldung:

1 Prelude> fst [2,3]

2 <interactive>:2:5:

3 Couldn’t match expected type ‘(α, β)’ with actual type ‘[Integer]’

4 — ...

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 126

Page 127: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Deklaration & Definition · 4.4

4.4 Deklaration & Definition

Haskell-Programm (Skript) = Deklarationen + Definitionen

Beispiel Fakultatsfunktion fact

1 fact :: Integer -> Integer

2 fact n = if n == 0

3 then 1

4 else n * fact (n-1)

I Deklaration fact :: Integer -> Integer

fact ist eine Funktion, die einen Wert des Typs Integer (ganze Zahl)auf einen Wert des Typs Integer abbildet.

I Definition fact n = ...(Rekursive) Regeln fur die Berechnung der Fakultatsfunktion.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 127

Page 128: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Basis-Typen · 4.5

4.5 Basis-Typen

I Haskell stellt diverse Basis-Typen zur Verfugung. Die Notation furKonstanten dieser Typen ahnelt anderen Programmiersprachen.

Ganze Zahlen: Integer

I Der Typ Integer enthalt die ganzen Zahlen, der Wertebereich istunbeschrankt. Haskell kennt auch den Typ Int, fixed precisionintegers, mit Wertebereich [−229, 229 − 1]

I Eine nichtleere Sequenz von Ziffern 0...9 stellt ein Integer-Literal dar.(kann aber auch als anderer numerischer Typ aufgefasst werden, cf. PK2, oder spater)

I Allgemein werden negative Zahlen durch die Anwendung der Funktionnegate oder des Prefix-Operators - gebildet.

I Achtung: Operator - wird auch zur Subtraktion benutzt, wie etwa in

f -123 6≡ f (-123)

I Beispiele: 0, 42,1405006117752879898543142606244511569936384000000000

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 128

Page 129: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Basis-Typen · 4.5

Konstanten des Typs Char (Zeichen)

I Zeichenkonstanten werden durch Apostrophe ’ · ’ (ASCII 39) eingefasst.

I Nichtdruckbare und Sonderzeichen werden mit Hilfe des bspw. auch in Cverwendeten \ (escape, backslash) eingegeben. Nach \ kann einASCII-Mnemonic (etwa NUL, BEL, FF, ...) oder ein dezimaler (oderhexadezimaler nach \x bzw. oktaler nach \o) Wert stehen, der denASCII-Code des Zeichens festlegt.

I Zusatzlich werden die folgenden Abkurzungen erkannt:

\a (alarm) \b (backspace) \f (formfeed)\n (newline) \r (carriage return) \t (Tab)\v (vertical feed) \\ (backslash) \" (dbl quote)\’ (apostroph) \& (NULL)

I Beispiele: ’P’, ’s’, ’\n’, ’\BEL’, ’\x7F’, ’\’’, ’\\’

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 129

Page 130: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Basis-Typen · 4.5

Konstanten des Typs Float (Fließkommazahlen)

I Fließkommakonstanten enthalten stets einen Dezimalpunkt. Vor undhinter diesem steht mindestens eine Ziffer 0...9.

I Die Konstante kann optional von e bzw. E und einem ganzzahligenExponenten (zur Basis 10) gefolgt werden.

I Beispiele: 3.14159, 10.0e-4, 0.001, 123.45E6

Konstanten des Typs Bool (Wahrheitswerte)

I Bool ist ein Summentyp (Aufzahlungstyp, enumerated type) und besitztlediglich die beiden Konstanten21 True und False.

21Spater: Konstruktoren.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 130

Page 131: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Funktionen · 4.6

4.6 Funktionen

Funktionen in funktionalen Programmiersprachen sind tatsachlich immathematischen Sinne zu verstehen. Ein Wert f mit

f :: α -> β

bildet bei Anwendung Objekte des Typs α auf Objekte des Typs β ab undes gilt22

x = y ⇒ f x = f y

Diese einfache aber fundamentale mathematische Eigenschaft vonFunktionen zu bewahren, ist die Charakteristik funktionalerProgrammiersprachen.

22Referenzielle Transparenz, cf. spaterStefan Klinger · DBIS Informatik 2 · Sommer 2016 131

Page 132: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Funktionen · 4.6

I Variablennamen, und damit auch die Namen von Funktionen23

beginnen mit Kleinbuchstaben a...z gefolgt von a...z, A...Z, 0...9, _ und ’.Als RegEx:

[a− z][a− z A− Z 0− 9 _’]∗

Beispiele: foo, c_3_p_o, f’

I Haskell ist case-sensitive, i.e., foobar 6≡ fooBar.

I Die Funktionsapplikation ist der einzige Weg in Haskell komplexereAusdrucke zu bilden. Applikation wird syntaktisch durch Juxtaposition(Nebeneinanderschreiben) ausgedruckt:Beispiel: Anwendung von Funktion f auf die Argumente x und y:

f x y

I Die Juxtaposition hat hohere Prioritat als Infix-Operatoren:

f x + y ≡ (f x) + y

I Klammern ( · ) konnen zur Gruppierung eingesetzt werden.23bis auf Operatoren, cf. Seite 133Stefan Klinger · DBIS Informatik 2 · Sommer 2016 132

Page 133: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Funktionen · 4.6

Operatoren

I Operatoren sind nichts anderes als Funktionen mit besonderensyntaktischen Eigenschaften (andere Zeichen, meist infix notiert).

I Haskell erlaubt die Einfuhrung neuer Infix-Operatoren. Operatorenerfullen den RegEx [

!#$%&*+/<=>?@^|~:.]+

I Ubliche Infix-Operatoren (+, *, ==, <, ...) sind bereits vordefiniert.

I Operatoren, die mit : beginnen, spielen eine Sonderrolle (cf. Seite 272,Algebraische Datentypen).

I Die Token .., :, ::, =, \, |, <-, ->, @, ~, =>, -- sind reserviert, ebensoder einzige unare Prafix-Operator - (Minus).

Beispiel Definition von ~~ als “fast gleich”:

1 epsilon :: Float

2 epsilon = 1.0e-4

3

4 (~~) :: Float -> Float -> Bool

5 x ~~ y = abs (x-y) < epsilon

1 > pi ~~ 3.141

2 False

3 > pi ~~ 3.1415

4 True

5 >

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 133

Page 134: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Funktionen · 4.6

Operatoren sind Funktionen

Infix-Operator → Prefix-Applikation. Jeder Infix-Operator � kann in derNotation (�) auch als Prefix-Operator geschrieben werden (cf. Seite 139):

1 + 3 ≡ (+) 1 3

True && False ≡ (&&) True False

Funktion → Infix-Applikation. Umgekehrt kann man jede binareFunktion f (Funktion zweier Argumente) mittels der Schreibweise ‘f‘

(ASCII 96) als Infix-Operator verwenden:

max 2 5 ≡ 2 ‘max‘ 5

I Die so notierten Infix-Operatoren werden durch die Sprache alslinks-assoziativ und mit hochster Operatorprioritat (Level 9) interpretiert:

5 ‘max‘ 3 + 4 _ 9

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 134

Page 135: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Funktionen · 4.6

Bemerkung: Information uber die Assoziativitat und Prioritat einesOperators durch den Interpreter:

1 > :i +

2 class (Eq a, Show a) => Num a where

3 (+) :: a -> a -> a

4 ...

5 -- Defined in GHC.Num

6 infixl 6 +

Die letzte Zeile verrat uns:

I + ist linksassoziativ,

I und hat prioritat 6.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 135

Page 136: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Funktionen · 4.6

Currying

I Prinzipiell hat jede in Haskell definierte Funktion nur einen Parameter.

I Funktionen mehrerer Parameter werden durch Currying realisiert(cf. oben).

I Der Typ einer Funktion mehrerer Parameter, etwa max : N×N→ N wirddargestellt als

max :: Integer -> Integer -> Integer

I Damit max eine Funktion eines Integer-Parameters, die bei Anwendungeinen Wert (hier: wieder eine Funktion) des Typs Integer -> Integer

liefert. Dieser kann dann auf ein weiteres Integer-Argument angewandtwerden, um letzlich das Ergebnis des Typs Integer zu bestimmen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 136

Page 137: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Funktionen · 4.6

Currying im λ-Kalkul:

I Haskell-Funktionsdefinitionen sind tatsachlich lediglich syntaktischerZucker fur die schon bekannten λ-Abstraktionen:

f x = e ≡ f = λx. eg x y = e ≡ g = λx y. e

I Damit lasst sich Currying durch mehrfache β-Reduktion erklaren.

Beispiel Maximumsfunktion:

1 max :: Integer -> Integer -> Integer

2 max x y = if x<y then y else x

max = λx y . if (x < y) y x

max 2 5

≡ Definition von max

(λx y . if (x < y) y x) 2 5_β (λy . if (2 < y) y 2) 5_β if (2 < 5) 5 2

∗5

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 137

Page 138: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Funktionen · 4.6

Partielle Anwendung

Currying erlaubt die partielle Anwendung von Funktionen. Der Wert desAusdrucks (+) 1 hat den Typ Integer -> Integer und ist dieFunktion, die 1 zu ihrem Argument addiert.

Beispiel Nachfolgerfunktion inc:

1 inc :: Integer -> Integer

2 inc = (+) 1

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 138

Page 139: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Funktionen · 4.6

Sections

I Currying ist auch auf binare Operatoren anwendbar, da Operatoren jalediglich binare Funktionen in Infix-Schreibweise (mit festgelegterAssoziativitat) sind. Man erhalt dann die sogenannten Sections.

I Fur jeden Infix-Operator � gilt (die Klammern ( · ) gehoren zur Syntax!):

(x �) ≡ λy. x � y

(� y) ≡ λx. x � y

(�) ≡ λx y. x � y

Beispiel Sections erlauben viele elegante Notationen:

1 inc = (1+)

2 halve = (/2)

3 add = (+)

4 positive = (‘max‘ 0)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 139

Page 140: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Funktionen · 4.6

λ-Abstraktionen (anonyme Funktionen)

I Haskell erlaubt λ-Abstraktionen als Ausdrucke und somit anonymeFunktionen, i.e., Funktionen ohne Namen.

I Die Notation ahnelt dem λ-Kalkul:

λx . e ≡ \x -> eλx . λy . e ≡ \x -> \y -> eλx y . e ≡ \x y -> e

I Damit wird der Ausdruck “(\x -> 2*x) 3” zu 6 ausgewertet und dievorige Definition von max kann alternativ wie folgt geschrieben werden:

1 max :: Integer -> Integer -> Integer

2 max = \x y -> if x<y then y else x

I Auch hier erstreckt sich der Wirkungsbereich des λ bis zum Ende deslangsten gultigen Terms (cf. Seite 94), d.h.,

\x -> (f x) ≡ \x -> f x 6≡ (\x -> f) x

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 140

Page 141: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Listen · 4.7

4.7 Listen

Listen sind die primare Datenstruktur in funktionalen Programmiersprachen.

I Haskell unterstutzt die Konstruktion und Verarbeitung homogenerListen beliebigen Typs: Listen von Integer, Listen von Listen, Listenvon Funktionen, ...

I Der Typ von Listen, die Elemente des Typs α enthalten, wird mit [α]bezeichnet (gesprochen list of α). Listen sind also immer homogen, d.h.alle Elemente sind vom gleichen Typ.

I Die Struktur von Listen ist rekursiv:• Eine Liste ist entweder leer, notiert als [], genannt nil,• oder ein konstruierter Wert aus Listenkopf x (head) und Restliste xs (tail),

notiert als x:xs. Der Operator (:) heißt cons24

24Fur list construction.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 141

Page 142: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Listen · 4.7

Listen-Konstruktion

I [] und (:) sind Beispiele fur ”data constructors”, Funktionen, dieWerte eines bestimmten Typs konstruieren. Wir werden dafur nochzahlreiche Beispiele kennenlernen.

I Jede Liste kann mittels [] und (:) konstruiert werden:• Liste, die 1 bis 3 enthalt: 1:(2:(3:[]))• Der cons-Operator ist rechts-assoziativ, also aquivalent: 1:2:3:[]

I Syntaktische Abkurzung: [e1,e2,...,en] ≡ e1:e2:...:en:[]

Beispiele[] :: [α]

’z’:[] :: [Char]

[[1],[2,3],[]] :: [[Integer]]

(False:[]):[] :: [[Bool]]

[(<),(<=),(>),(>=)] :: [α -> α -> Bool]

[[]] :: [[α]]

Naturlich hat auch cons einen Typ: (:) :: α→ [α]→ [α].

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 142

Page 143: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Listen · 4.7

Arithmetische Sequenzen

[x..y] ≡ wenn x<=y dann [x,x+1,x+2,...,y] sonst [][x1,x2..y] ≡ Liste der Werte x1 bis y mit Schrittweite x2-x1

~

Fur Sequenzen vom Typ [Float] und [Double] ist dieAbbruchbedingung y + x2−x1

2 .

Beispiel

I Der Ausdruck [2 .. 6] wird zu [2, 3, 4, 5, 6] ausgewertet,

I [9, 7 .. 2] ergibt [9, 7, 5, 3].

I Aber: [0.1, 0.3 .. 0.6] _ [0.1, 0.3, 0.5, 0.7], weil0.6 + 0.3−0.1

2 ≥ 0.7.

I Die Abbruchbedingung kann weggelassen werden, um “unendliche”Listen zu erzeugen: [1, 5 ..]_ [1,5,9,13,17,21,...

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 143

Page 144: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Listen · 4.7

Listen-Dekomposition

I Mittels der vordef. Funktionen head und tail kann eine nicht-leere Listex:xs wieder in ihren Kopf und Restliste zerlegt werden:

head (x:xs) _ x

tail (x:xs) _ xs

head [] _ *** Exception: Prelude.head: empty list

tail [] _ *** Exception: Prelude.tail: empty list

I Die Funktion null :: [α] -> Bool bestimmt ob eine Liste leer ist.

null [] _ True

null [1,2,3] _ False

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 144

Page 145: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Listen · 4.7

Konstanten des Typs String (Zeichenketten)

I Zeichenketten werden in Haskell durch den Typ [Char] reprasentiert,eine Zeichenkette ist also eine Liste von Zeichen.

I Funktionen auf Listen konnen damit auch auf Strings operieren.

I Haskell kennt String als Synonym fur den Typ [Char] (realisiertdurch die Deklaration type String = [Char] (→ spater)).

I Strings werden in doppelten Anfuhrungszeichen " · " notiert.

Beispiel""

"AbC"

’z’:[] ≡ "z"

[’C’,’u’,’r’,’r’,’y’] ≡ "Curry"

head "Curry" _ ’C’

tail "Curry" _ "urry"

tail (tail "OK\n") _ "\n"

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 145

Page 146: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Tupel · 4.8

4.8 Tupel

I Tupel erlauben die Gruppierung von Werten unterschiedlicher Typen(im Gegensatz zu Listen, welche immer homogen sind).

I Ein Tupel (c1,c2,...,cn) besteht aus einer fixen Anzahl vonKomponenten ci :: αi .Der Typ dieses Tupels wird notiert als (α1,α2,...,αn).

Beispiele

(1, ’a’) :: (Integer, Char)

("foo", True, 2) :: ([Char], Bool, Integer)

([(*1), (+1)], [1..10]) :: ([Integer -> Integer], [Integer])

((1,’a’),True) :: ((Integer, Char), Bool)

I Die Position einer Komponente in einem Tupel ist signifikant. Es gilt

(c1,c2,...,cn) = (d1,d2,...,dm)

genau dann, wenn n = m und ∀i ; 1 ≤ i ≤ n. ci = di .

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 146

Page 147: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

4 · Haskell – Typen, Werte und einfache Definitionen Tupel · 4.8

Zugriff auf Tupel-Komponenten

I Der Zugriff auf die einzelnen Komponenten eines Tupels geschieht durchPattern Matching, cf. Seite 150.

Beispiel Zugriffsfunktionen fur die Komponenten eines 2-Tupels undTupel als Funktionsergebnis:

1 fst :: (α, β) -> α2 fst (x,y) = x

3

4 snd :: (α, β) -> β5 snd (x,y) = y

6

7 mult :: Integer -> (Integer, Integer -> Integer)

8 mult x = (x, (*x))

9

10 > snd (mult 3) 5

11 15

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 147

Page 148: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5Funktionsdefinitionen

Page 149: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen

Typischerweise analysieren Funktionen ihre Argumente, umFallunterscheidungen fur die Berechnung des Funktionsergebnisses zutreffen. Je nach Beschaffenheit des Argumentes wird ein bestimmterBerechnungszweig gewahlt.

Beispiel Summiere die Elemente einer Liste l:

1 sum :: [Integer] -> Integer

2

3 sum xs = if xs == []

4 then 0 -- 1○5 else head xs + sum (tail xs) -- 2○

sum hat den Berechnungszweig mittels if · then · else im Fall der leerenListe 1○ bzw. nichtleeren Liste 2○ auszuwahlen und im letzeren Fall explizitauf Kopf und Restliste von l zuzugreifen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 149

Page 150: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Pattern Matching und case · 5.1

5.1 Pattern Matching und case

I Pattern Matching erlaubt, fur jeden Berechnungszweig einer Funktion f

Muster pi1, ..., pik fur die erwartete Struktur der Argumente anzugeben.

I Wenn die Argumente von f den Mustern pi1, ..., pik entsprechen, wird derentsprechende Berechnungszweig ei ausgewahlt:

f :: α1 -> ... -> αk -> β

f p11 ... p1k = e1

f p21 ... p2k = e2...f pn1 ... pnk = en

Die ei mussen dabei einen gemeinsamen (allgemeinsten) Typ β besitzen.

Semantik Beim Aufruf f x1 ... xk ...

I werden die xj gegen die Muster pij (i = 1...n, von oben nach unten)“gematcht” und der erste Berechnungszweig gewahlt, bei dem einvollstandiger Match vorliegt.

I Wenn kein Match erzielt wird, bricht das Programm ab.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 150

Page 151: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Pattern Matching und case · 5.1

Definition Erlaubte Formen fur ein Pattern pij

I Variable v — Der Match gelingt immer; v wird an das aktuelleArgument xj gebunden und ist in ei verfugbar; Pattern mussen linearsein, d.h. eine Variable v darf nur einmal in einem Pattern auftauchen.

I Konstante c — Der Match gelingt nur mit einem Argument xj welcheszu c reduziert, d.h. xj _ c .

I Wildcard ‘_’ — Der Match gelingt immer, es wird aber keineVariablenbindung hergestellt. (don’t care)

I Tupel-Pattern (p1,p2,...,pm) — Der Match gelingt mit einemm-Tupel, dessen Komponenten mit den Pattern p1, ..., pm matchen.

I List-Pattern [] und (p:ps) — Wahrend [] nur auf die leere Listematcht, gelingt der Match mit (p:ps) fur jede nichtleere Liste, derenKopf das Pattern p und deren Rest das Pattern ps matcht.

~

Diese Definition ist aufgrund der beiden letzten Falle rekursiv.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 151

Page 152: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Pattern Matching und case · 5.1

Beispiel Funktion sum mittels Pattern Matching:

1 sum :: [Integer] -> Integer

2

3 sum [] = 0

4 sum (x:xs) = x + sum xs

Sowohl die Fallunterscheidung als auch der Zugriff auf head und tail desArguments geschehen nun elegant durch Pattern Matching.

Beispiel Funktion zur Bestimmung der ersten n Elemente einer Liste:

1 take :: Int -> [α] -> [α]2

3 take 0 _ = []

4 take _ [] = []

5 take n (x:xs) = x : take (n-1) xs

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 152

Page 153: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Pattern Matching und case · 5.1

Beispiel Berechne xn (kombiniert Wildcard und Tupel-Pattern):

1 power :: (Float, Integer) -> Float

2

3 power (_, 0) = 1.0

4 power (x, n) = x * power (x,n-1)

Beachte: power ist trotz der Ubergabe von x und n eine Funktion eines(tupelwertigen) Parameters. (Nur zur Demonstration von Tupel-Pattern)

~

Vorsicht Eine potentielle Fehlerquelle sind Definitionen wie diese:

1 foo :: (Integer,Integer) -> Integer

2

3 foo (x, y) = x + y -- 1○4 foo (0, _) = 0 -- 2○

Der Zweig 2○ wird auch bei einem Aufruf foo (0,5) nicht ausgewertet(das Pattern in Zweig 1○ uberdeckt das Pattern in Zweig 2○).Allgemein gilt: Spezialfalle vor den allgemeineren Fallen anordnen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 153

Page 154: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Pattern Matching und case · 5.1

Layered Patterns

I Auf die Komponenten eines Wertes e kann mittels Pattern Matchingzugegriffen werden. Oft ist in Funktionsdefinitionen aber gleichzeitig auchder Wert von e selbst interessant.

I Sei v eine Variable, p ein Pattern. Das Layered Pattern (as-Pattern)

v@p

matcht gegen e, wenn p gegen e matcht. Zusatzlich wird v an den Werte gebunden.

Beispiel Variante der Funktion within (cf. Seite 80). Schneide Liste vonNaherungswerten ab, sobald sich die Werte weniger als eps unterscheiden.

1 within’ :: Float -> [Float] -> [Float]

2 within’ _ [] = []

3 within’ _ [y] = [y]

4 within’ eps (y:rest@(x:_)) = if abs (x-y) < eps

5 then [y,x]

6 else y : within’ eps rest

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 154

Page 155: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Pattern Matching und case · 5.1

Nutzlichkeit von Layered Patterns

Aufgabe: Mische 2 bezuglich lt geordnete Listen (z.B. in der merge-Phasevon Mergesort):

merge (<) [1,3 .. 10] [2,4 .. 10] _ [1,2,3, ..., 10]

Beispiel Formulierung ohne as-Patterns

1 merge :: (α -> α -> Bool) -> [α] -> [α] -> [α]2

3 merge lt [] ys = ys

4 merge lt xs [] = xs

5 merge lt (x:xs) (y:ys) = if x ‘lt‘ y

6 then x : merge lt xs (y:ys)

7 else y : merge lt (x:xs) ys

Die Listenargumente werden erst mittels Pattern Matching analysiert, umdanach evtl. wieder via (:) identisch zusammengesetzt zu werden.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 155

Page 156: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Pattern Matching und case · 5.1

Beispiel Jetzt Formulierung mit as-Patterns:

1 merge :: (α -> α -> Bool) -> [α] -> [α] -> [α]2

3 merge lt [] ys = ys

4 merge lt xs [] = xs

5 merge lt l1@(x:xs) l2@(y:ys) = if x ‘lt‘ y

6 then x : merge lt xs l2

7 else y : merge lt l1 ys

I Hier ist die Listenrekonstruktion nicht notwendig.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 156

Page 157: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Pattern Matching und case · 5.1

case-Ausdrucke

I Pattern Matching ist so zentral, dass es nicht nur in Zweigen einerFunktionsdefinition, sondern auch als eigenstandige Form zurVerfugung steht.

case e of p1 -> e1

p2 -> e2...

pn -> en

I Der Wert des Ausdrucks e wird nacheinander gegen die Pattern pi(i = 1...n) gematcht.

I Falls der Match e auf pk gelingt, so ist der Wert des Gesamtausdrucks ek .Die Variablenbindungen aus pk stehen in ek zur Verfugung.

I Trifft kein Muster zu, so bricht das Programm ab. (Der Wert desAusdrucks ist dann ⊥ (bottom), s. spater).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 157

Page 158: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Pattern Matching und case · 5.1

Beispiel “Zipper” fur zwei Listen.

1 zip’ :: [a] -> [b] -> [(a, b)]

2

3 zip’ [] _ = []

4 zip’ _ [] = []

5 zip’ (x:xs) (y:ys) = (x, y) : zip xs ys

Die Fallunterscheidung konnte man genauso gut25 auch auf der rechtenSeite der Funktionsdefinition treffen:

1 zip :: [α] -> [β] -> [(α,β)]2

3 zip xs ys = case (xs, ys) of

4 ([], _) -> []

5 (_, []) -> []

6 (x:xs, y:ys) -> (x, y) : zip xs ys

Ubrigens In Haskell gehoren case-Ausdrucke zum innerstenSprachkern. Viele andere Sprachkonstrukte (insb. alle, die auf PatternMatching bauen) werden intern auf case zuruckgefuhrt.

25was ist lesbarer? praktischer?Stefan Klinger · DBIS Informatik 2 · Sommer 2016 158

Page 159: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Pattern Matching und case · 5.1

Sprachkern?

I Viele Programmiersprachen bieten verschiedene syntaktische Formenum das Gleiche auszudrucken.

I Beim Bau eines Compilers konnte man fur jede dieser Formen eigeneUbersetzungsregeln definieren.

! Mehr Arbeitsaufwand (Ubersetzungsregeln sind oft aufwandig).

! Drucken die unterschiedlichen Formen wirklich das Gleiche aus? Beweisen!

I Ublicherweise wird eine essentielle Kernsprache (aka. core language)definiert, die nur die notigsten Konstrukte der Sprache enthalt.

� Alle anderen Konstrukte (aka. syntactic sugar) konnen auf die Kernsprachezuruckgefuhrt werden.

� Ein Compiler fur die Kernsprache ist leichter zu konstruieren.

� Oft konnen Spracherweiterungen bequem als syntaktischer Zucker realisiertwerden ⇒ Kein Eingriff in den Sprachkern notig.

Der Ubergang zur Kernsprache ist typischerweise eine recht fruheUbersetzungsphase, cf. Seite 25.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 159

Page 160: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Pattern Matching und case · 5.1

case gehort zum Haskell Sprachkern — Beispiele

I Bedingte Ausdrucke werden mittels case implementiert

if e1 then e2 else e3 ≡ case e1 of True -> e2

False -> e3

• Damit wird die Forderung nach einem gemeinsamen allgemeinsten Typ α vone2 und e3 deutlich.

I Funktionsdefinitionen mit Pattern Matching werden intern incase-Ausdrucke uber Tupeln ubersetzt:

f p1 ... pk = e ≡ f v1 ... vk = case (v1,...,vk) of

(p1,...,pk) -> e

• Dabei sind v1, ..., vk neue Variablen.• So hat der Compiler lediglich die etwas einfachere Aufgabe,

Funktionsdefinitionen ohne Pattern Matching zu ubersetzen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 160

Page 161: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Guards · 5.2

5.2 Guards

I Oft ist die Analyse der Struktur der Argumente einer Funktion nichtausreichend, um den korrekten Berechnungszweig auszuwahlen.

I Guards bieten die Moglichkeit, zusatzlich beliebige Tests auszufuhren,wenn Zweige gewahlt werden:

f :: α1 -> ... -> αk -> βf p11 ... p1k | g11 = e11

| g12 = e12

| ... = ......

f pn1 ... pnk | gn1 = en1

| gn2 = en2

| ... = ...

I Die Guards gij sind Ausdrucke des Typs Bool.

I In den Guards gij (j ≥ 1) sind die durch die Pattern pi1...pikgebundenen Variablen nutzbar.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 161

Page 162: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Guards · 5.2

Semantik von Guards

...f pi1...pik | gi1 = ei1

| gi2 = ei2| ... = ...

...

I Falls die Pattern pi1, ..., pik matchen, werden die Guards gij der Reihenach von oben nach unten (j = 1, j = 2, . . .) getestet.• Der erste Guard gij der dabei zu True ausgewertet wird bestimmt eij als

Ergebnis von f.• Wird keiner der Guards gik erfullt, wird nach dem nachsten matchenden

Pattern gesucht.• Der spezielle Guard otherwise evaluiert immer zu True, nutzlich als

Default-Alternative.

I Guards konnen oft explizite Abfragen mittels if · then · else ersetzen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 162

Page 163: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Guards · 5.2

Beispiel Selektiere die Elemente einer Liste, die die Bedingung p erfullen.

1 filter :: (α -> Bool) -> [α] -> [α]2 filter p [] = []

3 filter p (x:xs) | p x = x : filter p xs

4 | otherwise = filter p xs

Beispiel Noch eine Variante von within:

1 within :: Float -> [Float] -> [Float]

2 within _ [] = []

3 within _ [y] = [y]

4 within eps (y:rest@(x:_))

5 | abs (x-y) < eps = [y,x]

6 | otherwise = y : within eps rest

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 163

Page 164: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Guards · 5.2

Beispiel Losche adjazente Duplikate aus einer Liste.

1 remdups :: [Integer] -> [Integer]

2

3 remdups (x:xs@(y:_)) | x == y = remdups xs

4 | otherwise = x : remdups xs

5 remdups xs = xs

Frage: Konnte der letzte Zweig auch remdups [] = [] geschriebenwerden?

Beispiel Ist ein Element e in einer absteigend geordneten Liste vorhanden?

1 elem’ :: Integer -> [Integer] -> Bool

2

3 elem’ _ [] = False

4 elem’ e (x:xs) | e > x = False

5 | e == x = True

6 | e < x = elem’ e xs

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 164

Page 165: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Guards · 5.2

I Guards konnen auch in case-Ausdrucken verwendet werden. Die Syntaxwird analog zu der von Funktionsdefinitionen erweitert:

case e of p1 | g11 -> e11

| g12 -> e12...

pn | gn1 -> en1

| gn2 -> en2...

Beispiel Entferne die ersten n Elemente einer Liste.

1 drop :: Integer -> [α] -> [α]2

3 drop n xs = case xs of

4 [] -> []

5 (x:xs) | n > 0 -> drop (n-1) xs

6 | n == 0 -> x:xs

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 165

Page 166: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Lokale Definitionen · 5.3

5.3 Lokale Definitionen

Es kann oft nutzlich sein, lediglich lokal sichtbare Namen in Ausdruckenzu verwenden. Dies dient

I der Beschrankung der Sichtbarkeit von Namen (Verbergen vonImplementationdetails),

I dem “Herausfaktorisieren” ofter auftretender identischerTeilausdrucke aus einem Ausdruck (kann die Effizienz der Auswertungsteigern).

Vgl. lokale Definitionen/Deklarationen in blockstrukturierten (imperativen)Sprachen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 166

Page 167: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Lokale Definitionen · 5.3

let-Ausdrucke

Wenn e, e1, . . . , en Haskell-Ausdruckesind, und p1, . . . , pn Patterns, so ist auchder let-Ausdruck rechts ein gultigerHaskell-Ausdruck.

let p1 = e1

p2 = e2...pn = en

in e

I Die Reihenfolge der Definitionen pi = ei ist unerheblich, sie durfenwechselseitig rekursiv sein.

I In e erscheinen die durch den Pattern-Match von ei gegen pi definiertenNamen an ihre Werte gebunden und sind außerhalb des Scopes von let

unbekannt.

Semantik Falls die ei nicht rekursiv sind (!) hat der obige let-Ausdruckden Wert

(λ p1 p2 ... pn . e) e1 e2 ... en

I Die Auswertung der ei geschieht also lazy: (ei wird nur dann tatsachlichausgewertet, wenn dies zur Auswertung von e erforderlich ist).

I Wir werden im Kapitel Typinferenz eine weitere Besonderheit sehen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 167

Page 168: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Lokale Definitionen · 5.3

Beispiel

I Wir vervollstandigen die Implementation von Mergesort (cf. Seite 155):

1 mergesort :: (α -> α -> Bool) -> [α] -> [α]2

3 mergesort lt [] = []

4 mergesort lt [x] = [x]

5 mergesort lt xs = let (l1,l2) = split xs

6 in merge lt (mergesort lt l1) (mergesort lt l2)

I Es verbleibt die Definition der fur Mergesort typischen Divide-Phasemittels split, die eine Liste xs in zwei Listen ungefahr gleicher Langeteilt (das Listenpaar wird in einem 2-Tupel zuruckgegeben).

I Frage: Wie ist eine Liste xs unbekannter Lange in zwei ca. gleich langeTeillisten l1, l2 zu teilen?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 168

Page 169: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Lokale Definitionen · 5.3

split, Version 1○ Teile in der Mitte (mit Funktion length).

1 split :: [α] -> ([α], [α])2

3 split xs = nsplit (length xs ‘div‘ 2) xs

4

5

6 nsplit :: Int -> [α] -> ([α], [α])7

8 nsplit n xs = (take n xs, drop n xs)

Besser: Verstecke Implementationsdetail nsplit in einem let-Ausdruck

1 split :: [α] -> ([α], [α])2

3 split xs = let nsplit n xs = (take n xs, drop n xs)

4 in nsplit (length xs ‘div‘ 2) xs

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 169

Page 170: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Lokale Definitionen · 5.3

Offensichtlicher Nachteil der split Version 1○: xs wird zweimaldurchlaufen.

split, Version 2○ Durchlaufe xs nur einmal, fuge dabei abwechselnd einElement in l1 oder l2 ein.

1 split2 :: [α] -> ([α], [α])2

3 split2 [] = ([], [])

4 split2 [x] = ([x], [])

5 split2 (x:x’:xs) = let (l1, l2) = split2 xs

6 in (x:l1, x’:l2)

Das Pattern (l1, l2) wird verwendet um das Ergebnis des rekursivenAufrufs von split2 aufzutrennen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 170

Page 171: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Lokale Definitionen · 5.3

where-Klauseln

I Lokale Definitionen lassen sichalternativ mit einer where-Klauseleinfuhren.

I Sie erweitert die Syntax vonFunktionsdefinitionen undcase-Ausdrucke ein weiteres Mal.

I Die dij sind jeweils in den Guards gikund Ausdrucken eik (k = 1...) desgesamten Definitionszweiges isichtbar. Dies lasst sich mitlet-Ausdrucken nicht formulieren.

I Fur die lokalen Definitionen dij geltendie zuvor bei let erklartenVereinbarungen.

f :: α1 -> ... -> αk -> β

f p11 ... p1k | g11 = e11

| g12 = e12

|... = ...where d11

d12...

f pn1 ...pnk | gn1 = en1

| gn2 = en2

|... = ...where dn1

dn2...

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 171

Page 172: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Lokale Definitionen · 5.3

I where-Klauseln sind in allen Guards und rechten Seiten eines Zweigessichtbar...

1 f x y | y > z = ... z ...2 | y == z = ... z ...3 | otherwise = ... z ...4 where z = x*x

Beispiel Euklids Algorithmus zur Bestimmung des großten gemeinsamenTeilers (ggT):

1 ggT :: Integer -> Integer -> Integer

2

3 ggT x y = ggT’ (abs x) (abs y)

4 where

5 ggT’ x 0 = x

6 ggT’ x y = ggT’ y (x ‘mod‘ y)

~

Mit let werden Ausdrucke konstruiert, dagegen gehort where zurSyntax der Funktionsdefinition bzw. zur Syntax von case-Ausdrucken.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 172

Page 173: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Lokale Definitionen · 5.3

Beispiel Endgultige Mergesort-Implementierung mittels where und let.

1 -- Divide-and-Conquer Sortierung einer Liste

2 mergesort :: (α -> α -> Bool) -> [α] -> [α]3

4 mergesort _ [] = []

5

6 mergesort _ [x] = [x]

7

8 mergesort lt xs

9 = let (l1,l2) = split xs

10 in merge (mergesort lt l1) (mergesort lt l2)

11 where

12

13 -- splitte eine Liste in zwei gleich lange Teile

14 split [] = ([],[])

15 split [x] = ([x],[])

16 split (x:x’:xs) = let (l1,l2) = split xs

17 in (x:l1,x’:l2)

18

19 -- mische zwei sortierte Listen

20 merge [] ys = ys

21 merge xs [] = xs

22 merge l1@(x:xs) l2@(y:ys)

23 | x ‘lt‘ y = x : merge xs l2

24 | otherwise = y : merge l1 ys

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 173

Page 174: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Layout (2-dimensionale Syntax) · 5.4

5.4 Layout (2-dimensionale Syntax)

I Haskells Syntax verzichtet auf Separator- oder Terminator-Symbolewie ‘;’, um bspw. einzelne Deklarationen voneinander abzugrenzen.

I Trotzdem analysiert Haskells Parser etwa den Ausdruck

1 let y = a * b

2 f x = (x+y)/y

3 in f c + f d

eindeutig wie erwartet (der let-Ausdruck definiert den Wert y und dieFunktion f) und nicht als

1 let y = a * b f

2 x = (x+y)/y

3 in f c + f d

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 174

Page 175: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Layout (2-dimensionale Syntax) · 5.4

Haskell erreicht dies durch eine 2-dimensionale Syntax (Layout):

I Die Einruckungen (Spalte im Quelltext) der einzelnen Deklarationenhinter dem Schlusselwort let wird zur Auflosung von Mehrdeutigkeitenherangezogen.

I Das Layout des Quelltextes ist relevant jeweils• in Funktionsdefinitionen und• nach den Schlusselworten

let where of do

(lokale Dekl.) (lokale Dekl.) (case-Alternativen) (monadische Seq.)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 175

Page 176: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Layout (2-dimensionale Syntax) · 5.4

Haskells Layout wird durch einfache Vereinbarungen definiert:

Abseits-Regel (off-side rule)

1. Das erste Token nach einem let, where, of oder do definiert die oberelinke Ecke einer Box.

ggT x y = ggT’ (abs x) (abs y)

where ggT’ x 0 = x

ggT’ x y =

ggT (x ‘rem‘ y)...x ‘rem‘ y = x - y * (x ‘div‘ y)

2. Das erste Token, das links von der Box im Abseits steht, schließt dieBox (hier: kgV):

ggT x y = ggT’ (abs x) (abs y)

where ggT’ x 0 = x

ggT’ x y =

ggT (x ‘rem‘ y)

x ‘rem‘ y = x - y * (x ‘div‘ y)

kgV x y = ...

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 176

Page 177: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Layout (2-dimensionale Syntax) · 5.4

Struktur innerhalb der BoxI Haskell kennt eine explizite Syntax in der Deklarationen/Alternativen

explizit gruppiert (mittels { · }) und voneinander trennt (mittels ‘;’) sind.• let besitzt bspw. die alternative Syntax:

let { d1 ; d2 ; ... ; dn ;? } in e

1. Vor der Box wird eine offnende Klammer { eingefugt,

2. hinter der Box wird eine schließende Klammer } eingefugt,

3. vor einer Zeile, die direkt an der linken Box-Grenze startet, wird einSemikolon ; eingefugt. (eine neue Deklaration/Alternative beginnt)

I Die explizite Syntax fur das ggT-Beispiel lautet daher:

1 ggT x y = ggT’ (abs x) (abs y)

2 where {ggT’ x 0 = x

3 ;ggT’ x y =

4 ggT (x ‘rem‘ y)

5 ;x ‘rem‘ y = x - y * (x ‘div ‘y)

6 }kgV x y = ...

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 177

Page 178: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Layout (2-dimensionale Syntax) · 5.4

Die Mehrdeutigkeit des ersten Beispiels wird wie folgt aufgelost (Box undexplizite Syntax):

let {y = a * b

;f x = (x+y)/y

}inf c + f d

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 178

Page 179: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Layout (2-dimensionale Syntax) · 5.4

I Die vorhergehenden Vereinbarungen zum Layout erlauben die expliziteNutzung von Semikolons ; um Deklarationen innerhalb einer Zeile zutrennen. Erlaubt ware beispielsweise

let d1 ; d2 ; d3

d4 ; d5

in e

I Der Parser fugt automatisch ein schließende Klammer } ein, wenn so einSyntaxfehler vermieden werden kann. Beispiel:

let x = 3 in x+x wird expandiert zu let {x = 3 }in x+x

I Sobald der Programmierer von sich aus Klammern { · } setzt, sind dieLayout-Regeln außer Kraft gesetzt.

I Kommentare (--... und {-...-}) werden bei der Bestimmung desAbseits-Tokens nicht beachtet.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 179

Page 180: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Layout (2-dimensionale Syntax) · 5.4

I Die Reichweite einer Funktionsdefinition wird ebenfalls mittels einerLayout-Box erklart:

split xs = nsplit ...

...

alle Zeilen, die rechts

von der Boxgrenzebeginnen, gehoren zurDefinition von split

nsplit 0 xs (l1,_) = ...

...

ein Token direkt an derlinken Grenze startet

eine neue Box

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 180

Page 181: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

5 · Funktionsdefinitionen Layout (2-dimensionale Syntax) · 5.4

Bibliographie

I Simon Thompson. Haskell: the Craft of Functional Programming.Addison-Wesley, 1997.

I Paul Hudak, John Peterson, and Joseph H. Fasel. A Gentle Introductionto Haskell. Yale University, University of California, 1997.http://haskell.org/tutorial/.

I Simon Marlow (editor). Haskell 2010 Language Report.https://www.haskell.org/onlinereport/haskell2010/.

I John Hughes, and Simon L. Peyton Jones (editors). Haskell 98: ANon-strict, Purely Functional Language.http://www.haskell.org/onlinereport/.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 181

Page 182: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

6Referenzielle Transparenz

Nach der alten Rechtschreibung: Referentielle Transparenz;engl.: referential transparency.

Page 183: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

6 · Referenzielle Transparenz

Betrachte 4 Anweisungen einer imperativen Programmiersprache (etwaPascal):

1 R := f(m)*n + f(n)*m; (* 1○ *)

2

3 R := f(m) + f(m); (* 2○ *)

4

5 R := 2 * f(m); (* 3○ *)

6

7 R := f(23) + g(42); (* 4○ *)

8

9 if f() and f() and f() then ... (* 5○ *)

I Hat die Reihenfolge der beiden Aufrufe von pop in 1○ einen Einfluss aufden Wert von R? Konnen beide Aufrufe parallel erfolgen?

I Sind die Anweisungen 2○ und 3○ aquivalent?

I Sind + und * kommutativ?

I Ist in 5○ eine Vereinfachung mittels der Aquivalenz“f() and f() ≡ f()” moglich?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 183

Page 184: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

6 · Referenzielle Transparenz

Seiteneffekte in imperativen Sprachen

Generell muss die Antwort hier nein lauten! Wo liegt das Problem?

I Um sein Resultat zu errechnen, kann f auf globale Variablen zugreifen,die sich von Aufruf zu Aufruf geandert haben konnen.

I f kann wahrend der Ausfuhrung die (Speicherinhalte der) Variablen m

und n andern, also Seiteneffekte erzielen.

Der Wert eines Ausdrucks (hier bspw. f)

I hangt nicht nur von diesem Ausdruck selbst (hier also der Definition vonf und fs Parametern), sondern vom Speicher- und Registerzustandder gesamten Maschine ab,

I wird beeinflusst von der Reihenfolge der Auswertung seinerTeilausdrucke.

Im mathematischen Sinne ist eine imperative Prozedur f eben keineFunktion, d.h.

x == y 6⇒ f x == f y

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 184

Page 185: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

6 · Referenzielle Transparenz

Keine Seiteneffekte in funktionalen Sprachen

In funktionalen Programmen stehen Namen fur Werte und nicht furSpeicherorte mit veranderlichem Inhalt.

Definition Referenzielle Transparenz

Eine Sprache heißt referenziell transparent, wenn der Wert einesAusdrucks nur von seinen freien Variablen abhangt.

Konsequenzen:

I Ein Name darf jederzeit durch den von ihm definierten Wert ersetztwerden. (Das eroffnet unter Umstanden Moglichkeiten fur Optimierungen.)

I Der Wert eines Ausdrucks ohne freie Variablen hangt nur von den Wertenseiner Teilausdrucke ab.(Es konnen keine Seiteneffekte durch Variablen-Updates entstehen.)

I Die Reihenfolge der Auswertung der Teilausdrucke ist irrelevant.Insbesondere ist parallele Auswertung moglich.(Ohne Seiteneffekte gibt es in der Ausdrucksauswertung keine Abhangigkeiten oderBeeinflussungen von außen.)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 185

Page 186: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

6 · Referenzielle Transparenz

Ausdrucksauswertung in funktionalen Sprachen ist referenzielltransparent:

I Ersetze Namen durch ihre Definitionen.

I Wende Funktionen auf Argumente an (β-Reduktion des λ-Kalkuls).

Ersetzung und Reduktion kann in beliebiger Reihenfolge (auch parallel)erfolgen.

Beispiel Sei square x = x · x .

square (3 + 4)

_ Def. +

square 7

_ Def. square

7 · 7_ Def. ·

49

square (3 + 4)

_ Def. square

(3 + 4) · (3 + 4)

_ Def. +

(3 + 4) · 7_ Def. +

7 · 7_ Def. ·

49

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 186

Page 187: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

6 · Referenzielle Transparenz

Referenzielle Transparenz. . .I ermoglicht einen einfacheren Zugang zur Programmverifikation.

• Einzelne Funktionen konnen unabhangig vom Rest eines großerenProgrammes analysiert werden.

I eroffnet die Moglichkeit, Programmtransformationen (etwa zurautomatischen Optimierung durch einen Compiler) auszufuhren, dienachweislich die Bedeutung des Programms nicht andern.• Aquivalenz von Ausdrucken ist im mathematischen Sinne beweisbar.

I erlaubt den Aufbau ganzer Programmalgebren.• Elemente dieser Algebren sind Programme, Operationen sind

Programmtransformationen.

I erlaubt effizientere Auswertung durch Techniken wie Memoization,Sharing, Common Subtree Elimination, oder Parallelisierung.• z.B. werden beim Sharing mehrfach verwendete Ausdrucke nur einmal

ausgewertet und durch Ihr Ergebnis ersetzt, cf. Seite 382.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 187

Page 188: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

6 · Referenzielle Transparenz

Interaktion mit der Welt?

Die Referenzielle Transparenz bereitet allerdings auch Probleme:

I Input/Output?

1 (λx. (x,x)) (putStr "foo")

2 (putStr "foo", putStr "foo")

1 getChar == getChar

I Zufall?

1 random == random

I Zeitsensitive Ausdrucke?

1 getClockTime == getClockTime

Konflikt zur referenziellenTransparenz:

Die Reihenfolge der Auswertungder Teilausdrucke ist irrelevant.

Der Wert eines Ausdrucks hangtnur von den Werten seinerTeilausdrucke ab.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 188

Page 189: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

6 · Referenzielle Transparenz

Ausweg

I/O und andere solche “real world”-Probleme waren lange Zeit Gegenstandvon intensiven, nicht immer erfolgreichen Arbeiten in der FPL Community.

⇒ Monadic I/O wird aktuell als die beste und sauberste Losung gesehen,mit solchen Umwelt-/Zustandsabhangigkeiten umzugehen.

I Darauf kommen wir erst gegen Ende des Semesters wieder zuruck...

Konsequenz Wir konnen erstmal nicht:

I Dateien lesen, schreiben, loschen, ...

I Zufallswerte erzeugen,

I nach der Uhrzeit fragen,

I irgendwie mit der Umwelt kommunizieren

I ...

Das macht nix: Wir werden trotzdem viele interessante Programme schreiben.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 189

Page 190: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

7Exkurs: Berechenbarkeit

Page 191: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

7 · Exkurs: Berechenbarkeit Machtigkeit von Programmiersprachen · 7.1

7.1 Machtigkeit von Programmiersprachen

Aus mathematischer Sicht ist ein Programm eine Funktion, die eineEingabe zusammen mit dem Zustand der Maschine vor Start desProgrammes abbildet auf eine Ausgabe und einen neuen Zustand nachProgrammende.

program :: (State, Input)→ (State,Output)

Diese Funktion ist nicht unbedingt auf jeder Eingabe definiert (es ist danninsbesondere eine partielle Funktion):

I Ein Programm kann fehlschlagen, z.B. bei Division durch Null. (Nagut,das konnte man noch als Zustand auffassen).

I Wichtiger: Ein Programm muss nicht terminieren (es kann sich“aufhangen”). Hier wird also kein definierter Zustand erreicht.

Offensichtliche Frage Was kann man uberhaupt berechnen?

Antwort Tatsachlich ist nicht jede Funktion berechenbar!

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 191

Page 192: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

7 · Exkurs: Berechenbarkeit Machtigkeit von Programmiersprachen · 7.1

Turing-Maschine

Die Turing-Maschine ist eine abstrakte Rechenmaschine26.

I von Neumann Computer (z.B. unsere PCs) entsprechenTuring-Maschinen mit nur endlichem Hauptspeicher.

Definition Berechenbare Funktionen

Genau die Funktionen die von einer Turing-Maschine berechnet werdenkonnen, heißen berechenbar.

I Eine Programmiersprache heißt turingmachtig, wenn man mit ihr jedeberechenbare Funktion ausdrucken (implementieren) kann.• Die meisten “Allzweck”-Programmiersprachen sind turingmachtig27.

Beispiele: java, Haskell, C, Assembler, der λ-Kalkul, Brainfuck, ...Beweis: Implementation einer Turing-Maschine in der jeweiligen Sprache.

• Praktische Bedeutung: Wir konnen prinzipiell jede berechenbare Funktionimplementieren.

26Vorlesung Konzepte der Informatik oder Theoretische Informatik27unter der Annahme es stunde unendlich viel Hauptspeicher zur Verfugung!Stefan Klinger · DBIS Informatik 2 · Sommer 2016 192

Page 193: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

7 · Exkurs: Berechenbarkeit Machtigkeit von Programmiersprachen · 7.1

Anmerkungen

I Wir machen bei diesen Betrachtungen keine Aussage uber Laufzeit undSpeicherbedarf des Programmes.

I Auch die Einfachheit der Implementierung ist hier nicht relevant.

I Die Definition von “berechenbar” (cf. Seite 192) ist zwar ausreichend,aber etwas unbefriedigend, falls wir kein offensichtlich “unberechenbares”Problem beschreiben konnen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 193

Page 194: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

7 · Exkurs: Berechenbarkeit Das Halteproblem · 7.2

7.2 Das Halteproblem

Das Halteproblem ist sowohl praktisch relevant, als auch ein klassischesBeispiel fur eine nicht berechenbare Funktion.

I Angenommen wir haben ein Programm p (z.B. in Form von Quellcode),das eine Eingabe x verarbeitet:

1 void p( Input x ) ... —in einer fiktiven, z.B. imperativen Sprache

I Es ware schon zu wissen, ob p bei einer bestimmten Eingabe x

terminiert, oder “sich aufhangt”.

• Diese Frage ist das Halteproblem fur p(x).

• Ausprobieren ist keine Option. (Warum nicht?)

Frage Kann man ein Programm schreiben, welches entscheiden kann ob einubergebenes Programm (durch dessen Analyse) terminiert, welches alsodas Halteproblem beantwortet?

Anwort Nein, es ist im Allgemeinen nicht berechenbar, ob ein Programmhalt. (Im Speziellen, fur manche Programme also, ist dies moglich.)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 194

Page 195: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

7 · Exkurs: Berechenbarkeit Das Halteproblem · 7.2

Beweisskizze Beweis durch Widerspruch

Angenommen wir hatten ein Programm halts,

1 Bool halts( Sourcecode p, Input x ) { ... } —in einer fiktiven imperativen Sprache

welches fur jedes beliebige Programm p und jede beliebige Eingabe x

berechnen kann, ob das Programm p mit Eingabe x terminiert:

halts(p, x)_ True ⇐⇒ p(x) terminiert

halts(p, x)_ False ⇐⇒ p(x) terminiert nicht

Beispiel Anwendung auf ein terminierendes Programm:

1 void test1( Input x ) { print(x); }

1 > test1("hello world")

2 hello world

3 > halts(test1, "hello world")

4 True

1 > test1(test1)

2 void test1( Input x ) { print(x); }3 > halts(test1, test1)

4 True

~

Anmerkung Wir identifizieren hier Programme mit ihrem Quellcode.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 195

Page 196: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

7 · Exkurs: Berechenbarkeit Das Halteproblem · 7.2

Beispiel Anwendung auf ein nicht immer terminierendes Programm:

1 Int test2( Input x ) {2

3 while( x > 0 ) {4 x := 4;

5 }6

7 return 42;

8 }

1 > halts(test2, -23)

2 True

3 > test2(-23)

4 42

5 > halts(test2, 23)

6 False

7 > test2(23)

8 ... terminiert nicht

Erinnerung Das Programm halts terminiert auf jeden Fall.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 196

Page 197: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

7 · Exkurs: Berechenbarkeit Das Halteproblem · 7.2

Wir konstruieren einen Widerspruch

Erinnerung halts(p, x) berechnet, ob p(x) terminiert.

I Konstruieren jetzt ein Programm evil wie folgt:

1 Int evil( Sourcecode p ) {2

3 if (halts(p, p)) {4 while (True) {} —Endlosschleife5 }6

7 return 1;

8 }

• halts wendet das ubergebeneProgramm p auf p selbst an. Dashatten wir schon, cf. Seite 195.

• evil kann in einer Endlosschleifehangen bleiben.

Frage Terminiert evil fur ein gegebenes Programm p?

p(p) terminiert⇒

halts(p, p)_ True⇒

evil(p) terminiert nicht

p(p) terminiert nicht⇒

halts(p, p)_ False⇒

evil(p) terminiert

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 197

Page 198: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

7 · Exkurs: Berechenbarkeit Das Halteproblem · 7.2

Erinnerung Bis jetzt haben wir ein Programm evil konstruiert:

evil(p) terminiert⇔

p(p) terminiert nicht

1 Int evil( Sourcecode p ) { ... }

I Jetzt wenden wir evil auf sich selbst an.

I Terminiert evil(evil)?

Aus der Konstruktion folgt:

evil(evil) terminiert ⇔ evil(evil) terminiert nicht

Ein Widerspruch. Also muss unsere Annahme (die Existenz von halts)falsch sein. �

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 198

Page 199: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

7 · Exkurs: Berechenbarkeit Das Halteproblem · 7.2

Anmerkungen

I Es sieht hier so aus als ware dieser Beweis unabhangig vomRechenmodell. Ein formaler Beweis bezieht sich jedoch z.B. auf dieTuring-Maschine, und verwendet keine “fiktive imperativeProgrammiersprache”.

I Es ist tatsachlich kein machtigeres Konzept fur eine Rechenmaschinebekannt.

I Turing-Maschine und der einfache untypisierte λ-Kalkul (den wir bisherbesprochen haben) sind gleich machtig.• Auch im λ-Kalkul konnen wir nicht alles berechnen, ...• ...aber kein formales System kann mehr berechnen.• Beweisidee: Im λ-Kalkul eine Turing-Maschine beschreiben, und umgekehrt.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 199

Page 200: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

7 · Exkurs: Berechenbarkeit Konsequenzen · 7.3

7.3 Konsequenzen

Fur die Theorie...

I Es gibt tatsachlich Funktionen die prinzipiell nicht berechenbar sind(Man sagt auch: unentscheidbare Probleme).

...aber auch fur die Praxis:

I Wir konnen kein Programm bauen, das im Allgemeinen entscheiden kann,ob sich ein gegebenes Programm “aufhangt”.

I Dieses Problem erstreckt sich bereits auf Teile von Programmen:

1 Anweisung 1;

2 Anweisung 2;

3 ...4 Anweisung n;

5 print("hello");

• Die Anweisungen 1–n formen bereits einTeilprogramm.

• Im Allgemeinen ist also nicht entscheidbar, obdie Anweisung in Zeile 5 jemals ausgefuhrt wird.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 200

Page 201: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

7 · Exkurs: Berechenbarkeit Konsequenzen · 7.3

Bedeutung fur Compiler

I Ein Compiler hat auch die Aufgabe in unseren Programmen Fehler zufinden, damit sie nicht erst im Betrieb auffallen.• Dazu gehoren “offensichtliche” Fehler wie z.B. falsche Syntax,• weniger offensichtliche, wie nicht deklarierte Variablen oder Typfehler,• und Fehler wie das “Absturzen” (unerwarteter Zustand) oder “Aufhangen”

(nicht-Erreichen eines definierten Zustandes).

I Dazu bieten sich zwei Strategien an:

1. Alles zuruckweisen von dem der Compiler nicht beweisen kann, dass eskorrekt ist.

I Das ist eine sehr starke Einschrankung. Solche Sprachen lassen viele legitimeProgramme nicht mehr zu.

I Der Simply Typed λ-Calculus28 ist ein Beispiel dafur. Dieser ist nichtturingmachtig, dafur terminieren alle damit formulierten Programme.

2. Nur verbieten was der Compiler als definitiv falsch erkennt.I Hier wurde die Grenze der erkennbaren Fehler immer weiter verschoben.

Typsysteme sind eine Methode dazu.

28Eine Variante des λ-Kalkuls auf die wir nicht weiter eingehen werden.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 201

Page 202: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8Listenverarbeitung

Page 203: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung

I Funktionen, die Listen als Argumente besitzen, orientieren sich oft ander rekursiven Struktur von Listen (cf. Seite 141):

Rekursionsabbruch Das Argument ist die leere Liste [] :: [α], oderRekursion das Argument ist von der Form x:xs mit x :: α und xs :: [α].

I Die Definition einer listenverarbeitenden Funktion f :: [α]→ β nutztdaher oft eine entsprechende Fallunterscheidung

f [ ] = zf (x : xs) = c (h x) (t xs)

wobei• z :: β das Ergebnis bei Rekursionsabbruch darstellt, und

• im RekursionsfallI h :: α→ γ auf den Kopf (head), undI t :: [α]→ δ auf den Rest (tail) des Arguments angewandt werden,I wahrend c :: γ → δ → β das Ergebnis beider Aufrufe kombiniert.

Dabei ruft t typischerweise f selbst rekursiv auf.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 203

Page 204: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung

Beispiel Die Summe uber eine Liste

1 sum :: [Integer] -> Integer

2 sum [] = 0

3 sum (x:xs) = x + sum xs

1 > sum [1..10]

2 55

I Dabei sind z = 0, h = id, t = sum und c = (+).

I Die Identitatsfunktion id :: α→ α ist Teil der standard prelude und hatdie Definition id = \x -> x, also id = λx . x

Beispiel map f wendet die Funktion f auf jedes Element einer Liste an.

1 map :: (α -> β) -> [α] -> [β]2 map f [] = []

3 map f (x:xs) = f x : map f xs

1 > map (+1) [1..10]

2 [2, 3, 4, 5, 6, 7, 8, 9, 10, 11]

I Dabei sind z = [], h = f, t = map f und c = (:).

I Man sagt auch: Eine Funktion uber eine Liste mappen.

Frage Welche Funktion f erhalt man mittelsz = False, h = (e ==), t = f e und c = ||?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 204

Page 205: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung

Haskells Standard Prelude definiert nutzliche Funktionen uber Listen:

1 head (x:_) = x

2 tail (_:xs) = xs

3

4 init [x] = []

5 init (x:xs) = x : init xs

6

7 last [x] = x

8 last (_:xs) = last xs

9

10 length [] = 0

11 length (_:xs) = 1 + length xs

12

13 (x:_) !! 0 = x

14 (_:xs) !! n | n>0 = xs !! (n-1)

15

16 take n _ | n <= 0 = []

17 take _ [] = []

18 take n (x:xs) = x : take (n-1) xs

19 — analog: drop20

21 reverse [] = []

22 reverse (x:xs) = reverse xs ++ [x]

1 zipWith _ [] _ = []

2 zipWith _ _ [] = []

3 zipWith f (x:xs) (y:ys)

4 = f x y : zipWith f xs ys

5

6 zip = zipWith (,)

7

8 filter _ [] = []

9 filter p (x:xs)

10 | p x = x : filter p xs

11 | otherwise = filter p xs

12

13 [] ++ ys = ys

14 (x:xs) ++ ys = x : xs ++ ys

15

16 concat [] = []

17 concat (xs:xss) = xs ++ concat xss

18

19 dropWhile _ [] = []

20 dropWhile p xs@(x:xs’)

21 | p x = dropWhile p xs’

22 | otherwise = xs

23 — analog: takeWhile

Typen? Funktionsweise? — Die tatsachliche Implementation weicht teilweise ab.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 205

Page 206: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung

Was ist Foldable? Sollten das nicht Listen sein?

I Moderne Versionen des GHCi zeigen fur manche Funktionenuberraschend einen Typ mit Foldable statt mit Listen an:

1 Prelude> :t length

2 length :: Foldable t => t a -> Int

I Das verstehen wir leider erst spater, cf. Seite 299.

I Vorerst stellen wir uns vor es ginge um Listen29, d.h., wir lesen

Foldable t ⇒ ... t α ... einfach als ... [α] ...

ersetzen also jedes t α durch [α].

Beispiele Wir verwenden zunachst nur:

null :: [α]→ Bool statt null :: Foldable t ⇒ t α→ Boollength :: [α]→ Int statt length :: Foldable t ⇒ t α→ Intconcat :: [[α]]→ [α] statt concat :: Foldable t ⇒ t [α]→ [α]

29Tatsachlich geht es um allgemeinere Datenstrukturen die wir aber wohl nicht besprechen werden.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 206

Page 207: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung foldr und foldl · 8.1

8.1 foldr und foldl

Das besprochene Rekursionsschema ist in der Standard Prelude mit zweiFunktionen, foldr (fold right) und foldl (fold left), implementiert.

foldr (auch bekannt unter dem Namen reduce)

I “reduziert” eine Liste vom Typ [α] zu einem Wert des Typs β.

I Informell gilt: (dabei ist ⊕ ein Infix-Operator des Typs α→ β → β)

foldr (⊕) z [x1, x2, ..., xn] ≡ x1 ⊕ (x2 ⊕ (· · · (xn ⊕ z) · · · ))

Damit ist foldr :: (α→ β → β)→ β → [α]→ β.

I Eselsbrucken: Die Klammerung ist rechts-assoziativ, und das z erscheint ganz rechts.

Ein mogliche Definition von foldr ist:

1 foldr :: (α -> β -> β) -> β -> [α] -> β2 foldr (⊕) z [] = z

3 foldr (⊕) z (x:xs) = x ⊕ foldr (⊕) z xs

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 207

Page 208: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung foldr und foldl · 8.1

Alternativ lasst sich der Effekt von foldr damit auch wie folgt illustrieren:

foldr (⊕) z (x1 : (x2 : (...( xn : [] )...)))↓ ↓ ↓ ↓ ↓ ↓ ↓

= (x1 ⊕ (x2 ⊕ (...( xn ⊕ z )...)))

I Die Funktion foldr ersetzt also alle Listen-Konstruktoren, und zwar• : durch ⊕, und• [] durch z .

Beispiel Viele Standardfunktionen lassen sich einfach mittels foldr

implementieren:sum = foldr (+) 0

product = foldr ? ?concat = foldr ? ?and = foldr ? ?or = foldr ? ?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 208

Page 209: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung foldr und foldl · 8.1

Losung: sum = foldr (+) 0

product = foldr (*) 1

concat = foldr (++) []

and = foldr (&&) True

or = foldr (||) False

I Mit der Behauptung sum so definieren zu konnen, behaupte ich eineAquivalenz von sum von Folie 204 und foldr (+) 0:

sum ≡ foldr (+) 0

(Die entsprechenden Beweise ggf. spater in den Ubungen.)

~

Obacht Wir hatten vereinbart (cf. Seite 111), dass zwei λ-Ausdruckee1, e2 aquivalent sind, gdw. sie zur gleichen Normalform m reduziert werdenkonnen, d.h.:

e1 ≡ e2 ⇔ ∃m. e1 _∗m ∧ e2 _∗m

Frage Was ist z.B. mit sum ≡ foldr (+) 0 — gibt es so ein m?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 209

Page 210: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung foldr und foldl · 8.1

Gleichheit von Funktionen Das Extensionalitatsprinzip

Antwort Leider nicht. Ohne Argumente konnen wir nicht weit reduzieren.

I Die Aussage dass sich zwei Funktionen gleich verhalten macht abernaturlich trotzdem Sinn.

I Deswegen erweitern wir unsere Definition von Aquivalenz etwas:

Definition Aquivalenz von Funktionen

Zwei Funktionen f , g heißen aquivalent gdw. sie fur das gleicheArgument aquivalente Ergebnisse liefern, d.h.:

f ≡ g ⇔ ∀x . f x ≡ g x

Fur die Aquivalenz auf der rechten Seite bemuhen wir diese Definitionerneut, oder verwenden die bekannte Aquivalenz von Seite 111.

I Dieses Prinzip ist in der Mengenlehre als Extensionalitatsprinzipbekannt. Man sagt auch: f und g sind extensional gleich.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 210

Page 211: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung foldr und foldl · 8.1

Monoid

Nochmal: sum ≡ foldr (+) 0

product ≡ foldr (*) 1

concat ≡ foldr (++) []

and ≡ foldr (&&) True

or ≡ foldr (||) False

Beobachtung All diesen Beispielen ist gemeinsam, dass ⊕ assoziativ istund sich z bzgl. dieser Operation neutral verhalt.

Definition Monoid

Eine Menge M mit einer binaren Verknupfung ⊕ :: M ×M → M heißtMonoid, genau dann, wenn (Dabei sei M das Universum der Quantoren)

I die Operation ⊕ assoziativ ist, ∀a b c . a⊕ (b ⊕ c) ≡ (a⊕ b)⊕ c

I und es ein Neutralelement e gibt. ∃e. ∀a. e ⊕ a ≡ a ≡ a⊕ e

Ubrigens: Falls ⊕ :: α→ β → β assoziativ ist gilt bereits α = β. Warum?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 211

Page 212: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung foldr und foldl · 8.1

I Naturlich kann foldr auch auf Strukturen angewendet werden, die keinenMonoid bilden:

Beispiel

1 filter p = foldr (\x xs -> if p x then x:xs else xs) []

2 length = foldr (\_ n -> 1+n) 0

3 reverse = foldr (\x xs -> xs ++ [x]) []

4 takeWhile p = foldr (#) []

5 where

6 x # xs | p x = x:xs

7 | otherwise = []

Damit konnte takeWhile (<3) [1..4] etwa wie folgt reduziert werden:

1 takeWhile (<3) [1..4] _ foldr (#) [] (1 : (2 : (3 : (4 : []))))

2 _ 1 # (2 # (3 # (4 # [])))

3 _ 1 : (2 # (3 # (4 # [])))

4 _ 1 : (2 : (3 # (4 # [])))

5 _ 1 : (2 : [])

6 _ [1,2]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 212

Page 213: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung foldr und foldl · 8.1

Linksassoziative Variante von foldr

Analog zu foldr gibt es die vordefinierte Funktion foldl.

foldl (also fold left)

I klammert die Listenelemente wahrend der Reduktion nach links.

I Informell gilt: (dabei ist ⊗ ein Infix-Operator des Typs β → α→ β)

foldl (⊗) z [x1, x2, ..., xn] ≡ (· · · ((z ⊗ x1)⊗ x2) · · · )⊗ xn

Damit ist foldl :: (β → α→ β)→ β → [α]→ β

I Eselsbrucken: Die Klammerung ist links-assoziativ, und das z erscheint ganz links.

Ein mogliche Definition von foldl ist:

1 foldl :: (β -> α -> β) -> β -> [α] -> β2 foldl (⊗) z [] = z

3 foldl (⊗) z (x:xs) = foldl (⊗) (z ⊗ x) xs

Hier ubernimmt z die Rolle eines akkumulierenden Parameters, in demdas Endergebnis aufgesammelt wird.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 213

Page 214: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung foldr und foldl · 8.1

Beispiel Eine praktische Anwendung von foldl ist die Funktion pack, dieeine Liste von Ziffern [xn−1, xn−2, ..., x0] mit xi ∈ {0...9} in den durch sie“dargestellten” Wert transformiert:

n−1∑k=0

xk · 10k

1 pack :: [Integer] -> Integer

2 pack xs = foldl (#) 0 xs

3 where n # x = 10 * n + x

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 214

Page 215: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung foldr und foldl · 8.1

Das 1. Dualitatstheorem

I Auch hier gilt: Falls ⊗ :: β → α→ β assoziativ ist, dann ist α = β.

I Dann haben foldl und foldr den gleichen Typ:

foldr, foldl :: (α→ α→ α)→ α→ [α]→ α

Es gilt sogar:

Satz 1. Dualitatstheorem

Falls (⊗, α) einen Monoid mit Neutralelement e bilden, dann gilt:

foldr (⊗) e ≡ foldl (⊗) e

Beweis Evtl. Ubung, nach Kapitel uber Induktion (cf. Seite 226). �

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 215

Page 216: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung foldr und foldl · 8.1

Unmittelbare Konsequenz:

I Die Funktionen von Seite 211 konnen wir auch mit foldl bauen.

sum ≡ foldl (+) 0

product ≡ foldl (*) 1

concat ≡ foldl (++) []

and ≡ foldl (&&) True

or ≡ foldl (||) False

I Es bleibt zu klaren welche Variante effizienter ist. Das machen wir spatergenauer.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 216

Page 217: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung foldr und foldl · 8.1

Das 2. Dualitatstheorem

Auch ohne einen Monoid sind foldr und foldl eng verwandt:

Satz 2. Dualitatstheorem

Falls fur alle x , y , z geeigneten Typs gilt

x ⊕ (y ⊗ z) ≡ (x ⊕ y)⊗ zund

x ⊕ y ≡ y ⊗ x

dann giltfoldr (⊕) ≡ foldl (⊗)

Beweis Ubung, nach Kapitel uber Induktion (cf. Seite 226). �

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 217

Page 218: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung foldr und foldl · 8.1

Beispiel length = foldr (λ n. 1 + n) 0length′ = foldl (λn . 1 + n) 0

I Diese beiden Funktionen sind aquivalent.

I Die Variante mit foldl kann effizienter ausgewertet werden.(Dazu mussen wir aber noch mehr uber Auswertestrategien wissen, cf. spater.)

Beweis mit dem 2. Dualitatstheorem. Zu zeigen:

foldr (λ n. 1 + n)︸ ︷︷ ︸⊕

0 ≡ foldl (λn . 1 + n)︸ ︷︷ ︸⊗

0

I Zeigen x ⊕ z ≡ z ⊗ x :

x ⊕ z≡

1 + z≡

z ⊗ x

I Zeigen x ⊕ (y ⊗ z) ≡ (x ⊕ y)⊗ z :

x ⊕ (y ⊗ z)≡

1 + (y ⊗ z)≡

1 + (1 + y)

(x ⊕ y)⊗ z≡

1 + (x ⊕ y)≡

1 + (1 + y)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 218

Page 219: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung foldr und foldl · 8.1

Das 3. Dualitatstheorem

Schließlich gilt noch:

Satz 3. Dualitatstheorem

Sei reverse wie auf Seite 205 definiert, und sei flip f x y = f y x . Dann giltfur alle ⊕, z und xs geeigneten Typs:

foldr (⊕) z xs ≡ foldl (flip (⊕)) z (reverse xs)

Mit anderen Worten: Mit x ⊕ y ≡ y ⊗ x gilt:

foldr (⊕) z xs ≡ foldl (⊗) z (reverse xs)

Beweis Kann man als (aufwandige) Ubung machen, nach Kapitel uberInduktion (cf. Seite 226). �

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 219

Page 220: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung foldr und foldl · 8.1

Unendliche Listen

~

Vorsicht Eine Bemerkung zu foldl/foldr auf unendlichen Listen:

foldl (⊗) z (x:xs)

= foldl (⊗) (z ⊗ x) xs

foldr (⊕) z (x:xs)

= x ⊕ foldr (⊕) z xs

I Fur die nicht-leere Liste ruft sich foldl sofort rekursiv selbst auf, und dasErgebnis des rekursiven Aufrufs ist das Ergebnis der Funktion.

(Funktionen mit der zweiten Eigenschaft nennt man endrekursiv, tail recursive.)

I Bei foldr hangt das Ergebnis hingegen von ⊕ ab. Der rekursive Aufrufvon foldr ist nur Argument von ⊕.

⇒ Konsequenz:• foldl terminiert sicher nicht auf unendlichen Listen!• Bei foldr entscheidet der Operator ⊕ ob Rekursion stattfindet und kann

vor Ende der Liste abbrechen. (cf. Seite 212, takeWhile)

Beispiel head ≡ foldr const ⊥ Funktioniert auf unendlichen Listen.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 220

Page 221: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung foldr und foldl · 8.1

Anmerkungen

I Die Ersetzung der Konstruktoren eines Datentyps (hier fur Listen, alsocons (:) und nil []) durch Operatoren bzw. Werte ist ein Prinzip, dassich auch fur andere konstruierte Datentypen sinnvoll anwendenlasst.

I Im Gegensatz zu foldr ersetzt foldl nicht nur die Konstruktoren, sondernandert die Klammerung der rechtstief konstruierten Liste. Insofernnimmt es eine Sonderrolle ein.

Beide Punkte werden wir spater wieder aufgreifen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 221

Page 222: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung Effizienz · 8.2

8.2 Effizienz

Die Anzahl der Reduktionen bei der Reduktion eines Ausdrucks auf seineNormalform ist in FPLs ein naheliegendes Maß fur die Komplexitat einerBerechnung.

Beispiel Die Lange der ersten Argumentlistebestimmt die Anzahl der Reduktionen derListen-Konkatenation ++.

I ++.2 steht dabei fur die 2. Zeile derDefinition von ++, cf. Seite 205.

I Fur die Auswertung von xs ++ ys mitlength xs _ n werden n Reduktionen via++.2, gefolgt von einer Reduktion via ++.1benotigt.

I Die letzte Zeile ist lediglich eine Anderungder Schreibweise.

[3,2] ++ [1]

_ ++.2

3:([2] ++ [1])

_ ++.2

3:(2:([] ++ [1]))

_ ++.1

3:(2:[1])≡

[3,2,1]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 222

Page 223: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung Effizienz · 8.2

Beispiel Ahnliche Uberlegungen gelten fur reverse, das in seinerDefinition ++ nutzt:

reverse [1,2,3]

_ reverse.2

reverse [2,3] ++ [1]

_ reverse.2

(reverse [3] ++ [2]) ++ [1]

_ reverse.2

((reverse [] ++ [3]) ++ [2]) ++ [1]

_ reverse.1

(([] ++ [3]) ++ [2]) ++ [1]

_ ++.1

([3] ++ [2]) ++ [1]

_ ++.2, ++.1

[3,2] ++ [1]

_ ++.2, ++.2, ++.1

[3,2,1]

Gilt length xs _ n, dann benotigtreverse xs

I n Reduktionen via reverse.2,

I gefolgt von einer Reduktion viareverse.1,

I gefolgt von

1 + 2 + ... + n =n · (n + 1)

2

Reduktionen, um mittels ++ dieKonkatenationen auszufuhren.

Damit ist die Anzahl derReduktionen in O n2.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 223

Page 224: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung Effizienz · 8.2

Listeninvertierung in linearer Zeit

Eine Liste lasst sich aber durchaus in linearer Zeit (proportional zurListenlange n) reversieren:

1 rev :: [α] -> [α]2 rev xs = shunt [] xs

3 where

4 shunt ys [] = ys

5 shunt ys (x:xs) = shunt (x:ys) xs

I Tatsachlich reversiert shunt ys xs nicht nur die Liste xs, sondernkonkateniert diese zusatzlich auch noch mit ys.

I Das erste Argument ys von shunt wird akkumulierender Parametergenannt:• Zwischenergebnisse der Berechnung werden an die nachste Rekursion

weitergegeben.• Am Ende der Rekursion enthalt ys das Ergebnis (oder einen Teil davon).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 224

Page 225: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung Effizienz · 8.2

Beispiel rev xs benotigt lineare Anzahl (proportional zu (length xs))Reduktionen

rev [1,2,3]

_ rev.1

shunt [] [1,2,3]

_ shunt.2

shunt [1] [2,3]

_ shunt.2

shunt [2,1] [3]

_ shunt.2

shunt [3,2,1] []

_ shunt.1

[3,2,1]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 225

Page 226: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung Induktion uber Listen · 8.3

8.3 Induktion uber Listen

I Dank referenzieller Transparenz kann man Behauptungen wie

rev ≡ reverse

relativ einfach beweisen.

I Beweise uber listenverarbeitende Funktionen konnen haufig mittelsInduktion uber Listen, analog zu Induktionsbeweisen fur Behauptungenuber Elemente aus N, gefuhrt werden:

1. Induktionsanfang (aka. Induktionsverankerung).I Beweise die Aussage mit der leeren Liste [].

2. Induktionsschritt von xs zu x : xs.I Dabei wird die Induktionshypothese (die Aussage mit einer beliebigen, festen

Liste xs) verwendet, um die Aussage mit x : xs fur alle x zu zeigen.

Ubung Fur alle Listen xs gilt xs ++ [ ] ≡ xs.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 226

Page 227: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung Induktion uber Listen · 8.3

Beispiel Beweisen rev xs ≡ reverse xs fur alle Listen xs.

I Da rev xs _ shunt [ ] xs (cf. Seite 224), genugt es, die allgemeinereBehauptung zu zeigen:

shunt ys xs ≡ reverse xs ++ ys , fur alle xs, ys :: [α]

Induktionsverankerung Sei xs = [ ], und ys :: [α] beliebig.

shunt ys [ ] ≡ ys (shunt.1)≡ [ ] ++ ys (++.1)≡ reverse [ ] ++ ys (reverse.1)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 227

Page 228: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung Induktion uber Listen · 8.3

Induktionshypothese Fur ein beliebiges, festes xs :: [α], und fur alle ys :: [α]gelte:

shunt ys xs ≡ reverse xs ++ ys

Induktionsschritt Von xs zu x : xs. Seien x :: α, und ys :: [α].Mit dem xs aus der Induktionshypothese gilt:

shunt ys (x : xs) ≡ shunt (x : ys) xs (shunt.2)≡ reverse xs ++ (x : ys) (Hypothese)≡ reverse xs ++ (x : ([ ] ++ ys)) (++.1 ruckw.)≡ reverse xs ++ ([x ] ++ ys) (++.2 ruckw.)≡ (reverse xs ++ [x ]) ++ ys (++ assoziativ)≡ reverse (x : xs) ++ ys (reverse.2)

Ubung Die hier verwendete Annahme uber die Assoziativitat von ++ mussen wirebenfalls noch beweisen: xs ++ (ys ++ zs) ≡ (xs ++ ys) ++ zs. Auch hier fuhrtListeninduktion uber den Parameter zum Ziel, uber den die Rekursion der betrachtetenFunktion ++ formuliert ist, also xs.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 228

Page 229: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung Programm-Synthese · 8.4

8.4 Programm-Synthese

Bei der Beweisfuhrung uber Programme werden Eigenschaften einesgegebenen Programms Schritt fur Schritt nachvollzogen und dadurchbewiesen (s. rev und reverse).

Programm-Synthese kehrt dieses Prinzip um:

I Gegeben ist eine formale Spezifikation eines Problems,

I gesucht ist ein problemlosendes Programm, das durch schrittweiseUmformung der Spezifikation gewonnen (synthetisiert) wird.

Wenn die Transformationen diszipliniert vorgenommen werden, kann dieSynthese als Beweis dafur gelesen werden, dass das Programm dieSpezifikation erfullt (der Traum aller Software-Ingenieure).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 229

Page 230: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung Programm-Synthese · 8.4

Beispiel Die Funktion init der standard prelude bestimmt das initialeSegment ihres Listenargumentes, also etwainit [1..10] _ [1, 2, 3, 4, 5, 6, 7, 8, 9].

I Damit ware eine naheliegende Spezifikation fur init die folgende:

init xs = take (length xs - 1) xs wobei xs endlich und nicht leer

“Nimm alle Elemente von xs, aber nicht das letzte Element”

I Die Synthese versucht eine effizientere Variante von init abzuleiten(die Spezifikation ware ja prinzipiell schon ausfuhrbar, traversiert xs zurBerechnung des Ergebnisses aber zweimal).

Fur die Synthese instantiieren wir xs

1. mit [x ] und

2. mit x1 : x2 : xs.

Jede nichtleere Liste besitzt die eine oder die andere Form.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 230

Page 231: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung Programm-Synthese · 8.4

Fall 1 [x ]

init [x ] — Instanziierung

= Spezifikation

take (length [x ]− 1) [x ]

= length, Arithmetik

take 0 [x ]

= take.1

[ ]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 231

Page 232: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung Programm-Synthese · 8.4

Fall 2 x1 : x2 : xs

init (x1 : x2 : xs) — Instanziierung

= Spezifikation

take (length (x1 : x2 : xs)− 1) (x1 : x2 : xs)

= length, Arithmetik

take (length xs + 1) (x1 : x2 : xs)

= take.3

x1 : take (length xs) (x2 : xs)

= length.2, Arithmetik

x1 : take (length (x2 : xs)− 1) (x2 : xs)=

x1 : init (x2 : xs)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 232

Page 233: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung Programm-Synthese · 8.4

Zusammenfassen der beiden so erhaltenen Gleichungen ergibt

1 init :: [a] -> [a]

2 init [x] = []

3 init (x1:x2:xs) = x1 : init (x2:xs)

Weitere Verbesserungen

I Das wiederholte Zerlegen und Zusammensetzen der Liste x2 : xs kannman sich sparen.

I Fur die leere Liste geben wir einen brauchbaren Fehler aus.

1 init :: [a] -> [a]

2 init [x] = []

3 init (x:xs) = x : init xs

4 init [] = error "init: empty list"

Ubung Versuchen Sie Ihren Haskell-Code durch simpleAquivalenzumformungen zu verbessern. Manchmal gewinnt man dabeiuberraschende Einsichten.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 233

Page 234: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

8.5 List Comprehensions

List Comprehensions sind vor allem in modernen FPLs als eine alternativeNotation fur Operationen auf Listen verbreitet30.

I Die Notation mittels Set Comprehension31 ist aus der Mathematik(Mengenlehre) bekannt. Die Idee dabei:{

Term∣∣ Pradikat+

}• Beschreibt eine Menge, deren Elemente jeweils von Term beschrieben werden,• unter den durch die Pradikate bestimmten Bedingungen.

I List Comprehensions erweitern die Ausdruckskraft der Sprache nicht,erlauben aber oft eine kompakte, leicht lesbare und elegante Notationvon Listenoperationen.Wir werden eine Abbildung auf den Haskell-Kern besprechen.

30Miranda™ (Dave Turner, 1976) sah als erste FPL List Comprehensions syntaktisch vor.31aka. “set-builder notation”. Einen deutschen Begriff scheint’s nicht zu geben.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 234

Page 235: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Beispiel Die Menge aller naturlichen geraden Zahlen kann durch eineset comprehension kompakt notiert werden:

{n | n ∈ N, n mod 2 = 0}

Eine entsprechende List Comprehension (die unendliche Liste aller geradenZahlen) wird syntaktisch ganz ahnlich notiert:

[ n | n <- [0 .. ], n ‘mod‘ 2 == 0 ]

Beispiel Die Standardfunktionen map und filter sind mittels ListComprehensions ohne die sonst notwendige Rekursion formulierbar:

1 map :: (α -> β) -> [α] -> [β]2 map f xs = [ f x | x <- xs ]

1 filter :: (α -> Bool) -> [α] -> [α]2 filter p xs = [ x | x <- xs, p x ]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 235

Page 236: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Syntax der List Comprehension

Die allgemeine Form einer List Comprehension ist

[ e | q1, q2, ..., qn ]

wobei

I der Kopf e ein beliebiger Ausdruck ist, und

I die Qualifier qi (mit n ≥ 1), eine von drei Formen besitzen:

Generator pi <- ei , wobei ei :: [αi ], und pi ein Pattern fur Werte des Typsαi ist — schreiben salopp pi :: αi .

Pradikat qi :: Bool.

lokale Bindung let { pi1 = ei1; pi2 = ei2... }. Dabei sind die eij beliebigeAusdrucke, und die pij entsprechende Patterns.

Beispiel von vorhin: [ n | n <- [0 .. ], n ‘mod‘ 2 == 0 ] .

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 236

Page 237: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

ListComp → [ Expr | Qual (, Qual)∗ ] — Zusammenfassung

Qual → Pattern <- Expr — Pattern :: α, Expr :: [α]| Expr — Expr :: Bool| let { Pattern = Expr (; Pattern = Expr)∗ } — cf. Seite 167

Semantik der List Comprehension — in Worten

I Ein Generator qi = pi <- ei versucht das Pattern pi der Reihe nachgegen die Elemente der Liste ei zu matchen.• Fur jeden erfolgreichen Match werden die nachfolgenden Qualifier

qi+1, ..., qn ausgewertet.

• Die durch den Match gebundenen Variablen des Patterns pi sind in dennachfolgenden Qualifiern sichtbar und an entsprechende Werte gebunden.

I Eine lokale Bindung (let) kann ebenfalls Variablen an Werte binden.

I Jede Bindung wird solange nach rechts propagiert, bis ein Pradikatunter ihr zu False evaluiert wird.

I Der Kopf e wird fur alle Bindungen ausgewertet, die alle Pradikatepassieren konnten.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 237

Page 238: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Entsprechend dieser Semantik wird also in [ e | p1 <- e1, p2 <- e2 ]

I zuerst uber die Domain e1 des Generators p1 <- e1 iteriert, und dann

I fur jeden Match von p1 uber die Domain e2 des Generators p2 <- e2.

Dies trifft die Intuition der aus der Mengenlehre bekannten SetComprehension:

[ (x,y) | x <- [x1, x2], y <- [y1, y2] ]_

[(x1,y1), (x1,y2), (x2,y1), (x2,y2)]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 238

Page 239: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Beispiel Elegante (aber ineffiziente) Variante von Quicksort als 2-Zeiler

1 qsort :: (α -> α -> Bool) -> [α] -> [α]2 qsort _ [] = []

3 qsort (<) (x:xs) = qsort (<) [ y | y <- xs, y < x ]

4 ++ [x] ++

5 qsort (<) [ y | y <- xs, not (y < x) ]

Beachte: In der split-Phase dieser Implementation wird die Liste xs jeweils(unnotigerweise) zweimal durchlaufen.

Beispiel Matrix uber Typ α als Liste von Zeilenvektoren (wiederumListen). Bestimme ersten Spaltenvektor:

1 firstcol :: [[α]] -> [α]2 firstcol m = [ e | (e:_) <- m ]

firstcol nutzt die Moglichkeit, in Generatoren Patterns zu spezifizieren.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 239

Page 240: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Beispiel Alle Permutationen einer Liste xs

1. Die leere Liste [ ] hat sich selbst als einzige Permutation.

2. Wenn xs nicht leer ist, wahle ein Element a aus xs und stelle a denPermutationen der Liste xs ohne a voran.

3. Fuhre 2. fur jedes Element der Liste xs aus.

1 perms :: [Integer] -> [[Integer]]

2 perms [] = [[]]

3 perms xs = [ a:p | a <- xs, p <- perms $ xs \\ [a] ]

4

5 > perms [2, 3]

6 [[2, 3], [3, 2]]

I Dabei entfernt die Listendifferenz xs \\ ys alle Elemente von ys aus derListe xs, etwa: [1, 2, 1, 2, 3] \\ [2, 5] _ [1, 1, 3].

I Wie konnte man \\ implementieren?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 240

Page 241: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Beispiel Berechne alle Pythagoraischen Dreiecke mit Seitenlange ≤ n

1 pyth n = [ (a,b,c) | c <- [1..n], a <- [1..c], b <- [1..a], a^2 + b^2 == c^2 ]

2

3 > pyth 20

4 [(4,3,5),(8,6,10),(12,5,13),(12,9,15),(15,8,17),(16,12,20)]

Beispiel Was berechnet die folgende Funktion bar? Wie lautet ihr Typ?

1 bar xs = [ x | [x] <- xs ]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 241

Page 242: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Beispiel “Join” zwischen zwei Listen bzgl. eines Pradikates p

1 join :: (α -> β -> γ) -> (α -> β -> Bool) -> [α] -> [β] -> [γ]2 join f p xs ys = [ f x y | x <- xs, y <- ys, p x y ]

Den “klassischen relationalen Join” R1 onfst=fst R2 auf binaren RelationenRi , erhalt man dann durch

1 foo = join

2 (\x y -> (fst x, snd x, snd y))

3 (\x y -> fst x == fst y)

4 [(1, "John"), (2, "Jack"), (3, "Bonnie")]

5 [(2, "Ripper"), (1, "Doe"), (3, "Parker"), (2, "Dalton"), (1, "Cleese")]

6

7 Prelude> foo

8 [ (1, "John", "Doe"), (1, "John", "Cleese"), (2, "Jack", "Ripper")

9 , (2, "Jack", "Dalton"), (3, "Bonnie", "Parker")]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 242

Page 243: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Operationale Semantik fur List Comprehensions

Die Semantik der List Comprehensions, welche wir vorhin (cf. Seite 237)eher durch “hand-waving” erklart haben, lasst sich —ganz ahnlich wie beider β-Reduktion des λ-Kalkuls— durch Reduktionsregeln formal erklaren.

Definition Semantik der List Comprehension, ohne Pattern Matching

Sei e ein Haskell-Ausdruck, v Variable, qs eine Sequenz32 von Qualifiern.Die folgenden Regeln reduzieren jeweils den ersten Qualifier:

[ e | v <- [], qs ] _ [] 1○[ e | v <- (x : xs), qs ] _ [ e | qs ][v�x ]

++ [ e | v <- xs, qs ] 2○

[ e | False, qs ] _ [] 3○[ e | True, qs ] _ [ e | qs ] 4○

[ e | ] _ [ e ] 5○

32qs ist keine Haskell-Liste, sondern ein Konstrukt der Meta-Ebene, cf. Seite 237.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 243

Page 244: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

I Die ersten beiden Reduktionsregeln reduzieren einen Generator uber einerleeren 1○ bzw. nichtleeren 2○ Liste.

I Regeln 3○ und 4○ testen Pradikate.

I Regel 5○ ist anwendbar, sobald die Sequenz der Qualifier vollstandigreduziert wurde.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 244

Page 245: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Beispiel Reduktion von [ x^2 | x <- [1,2,3], odd x ]

[ x^2 | x <- [1,2,3], odd x ]

_ verwenden 2○

[ x^2 | odd x ][x�1] ++ [ x^2 | x <- [2,3], odd x ]︸ ︷︷ ︸A=

[ 1^2 | odd 1 ] ++ A_

[ 1^2 | True ] ++ A

_ verwenden 4○

[ 1^2 | ] ++ A

_ verwenden 5○

[1^2] ++ A_

1 :

A︷ ︸︸ ︷[ x^2 | x <- [2,3], odd x ]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 245

Page 246: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

1 : [ x^2 | x <- [2,3], odd x ]

_ verwenden 2○

1 : [ x^2 | odd x ][x�2] ++ [ x^2 | x <- [3], odd x ]︸ ︷︷ ︸B=

1 : [ 2^2 | odd 2 ] ++ B_

1 : [ 2^2 | False ] ++ B

_ verwenden 3○

1 : [] ++ B_

1 :

B︷ ︸︸ ︷[ x^2 | x <- [3], odd x ]

_ verwenden 2○

1 : [ x^2 | odd x ][x�3] ++ [ x^2 | x <- [], odd x ]

_ links wie gehabt (_ 9), und rechts verwenden wir 1○

1 : 9 : []=

[1, 9]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 246

Page 247: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Abbildung von List Comprehensions auf den Haskell-Kern

I Prinzipiell erlaubt das System der eben besprochenen Reduktionsregeln,List Comprehensions auf in Haskell vordefinierte Funktionenzuruckzufuhren.

I Im Folgenden betrachten wir ein Ubersetzungsschema J·K, das ListComprehensions aus Haskell-Code entfernt33:

JCode mit List Comprehension K = Code ohne List Comprehension

I J·K kann vom Compiler auf Haskell-Quellcode angewandt werden, umaquivalenten Code ohne List-Comprehensions zu erhalten.

33Hier verwenden wir semantische Klammern etwas anders als gewohnt.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 247

Page 248: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Dabei basiert das Schema J·K auf der Funktion concatMap:

1 concatMap :: (α -> [β]) -> [α] -> [β]2 concatMap f = foldr (\x xs -> f x ++ xs) []

Frage Was tut diese Funktion?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 248

Page 249: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

1 concatMap :: (α -> [β]) -> [α] -> [β]2 concatMap f = foldr (\x xs -> f x ++ xs) []

3

4 > concatMap (replicate 3) "hello"

5 "hhheeellllllooo"

Antwort concatMap f xs wendet die Funktion f auf jedes Element von xsan. Dabei gibt f jeweils eine Liste zuruck, welche von concatMapkonkateniert werden.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 249

Page 250: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Ubersetzungsschema J·K immer noch ohne Pattern Matching

Sei e ein Ausdruck, v eine Variable, b ein Boolescher Ausdruck, und qswieder eine Sequenz von Qualifiern.

J[ e | v <- xs, qs ]K = concatMap (λv . J[ e | qs ]K) JxsK 1○

J[ e | b, qs ]K = if JbK then J[ e | qs ]K else [] 2○

J[ e | ]K = [ JeK ] 3○

JeK = Wende J·K rekursiv auf alle nicht-primitivenTeilausdrucke von e an.

4○

I Wieder wird die Sequenz der Qualifier ( 1○: Generatoren; 2○: Pradikate)reduziert, bis 3○ den Fall ohne Qualifier behandeln kann.

I Regel 4○ steigt rekursiv im AST ab, um evtl. weitere ListComprehensions zu ubersetzen.

Frage Wozu brauchen wir JbK in Regel 2○, statt einfach b zu schreiben?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 250

Page 251: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Beispiel Ubersetzung von [ x^2 | x <- [1..5], odd x ]

J[ x^2 | x <- [1..5], odd x ]K= 1○

concatMap (λx. J[ x^2 | odd x ]K) J[1..5]K= 4○

concatMap (λx. J[ x^2 | odd x ]K) [1..5]

= 2○

concatMap (λx. if Jodd xK then J[ x^2 | ]K else []) [1..5]

= 3○ und 2× 4○

concatMap (λx. if odd x then [ x^2 ] else []) [1..5]

Frage Bisher haben wir Pattern Matching in unseremUbersetzungsschema J·K nicht berucksichtigt. Wo mussen wirnachbessern?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 251

Page 252: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Pattern Matching in List Comprehensions

Beispiel Was tut die Funktion heads? Was ist der Typ?

1 heads xs = [ y | (y:_) <- xs ]

Ubersetzen heads mit dem Ubersetzungsschema J·K:

Jλxs. [ y | (y:_) <- xs ]K= 4○

λxs. J[ y | (y:_) <- xs ]K= 1○, behandeln Pattern wie Variable

λxs. concatMap(λ(y:_). J[ y | ]K

)JxsK

= 3○, 1○

λxs. concatMap(λ(y:_). [y]

)xs

]η concatMap

(λ(y:_). [y]

)Frage Gilt heads ≡ concatMap

(λ(y:_). [y]

)?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 252

Page 253: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Antwort Nein: Wenn der Pattern Match gegen (y:_) fehlschlagt, wird dasProgramm abgebrochen!

1 > heads [[1],[2,3],[4,5,6]]

2 [1,2,4]

3 > concatMap (\(y:_)-> [y]) [[1],[2,3],[4,5,6]]

4 [1,2,4]

5

6 > heads [[1],[],[4,5,6]]

7 [1,4]

8 > concatMap (\(y:_)-> [y]) [[1],[],[4,5,6]]

9 [1*** Exception: <interactive>:23:12-23: Non-exhaustive patterns in lambda

Frage An welcher Stelle konnen wir das fixen?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 253

Page 254: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Definition Ubersetzungsschema J·K mit Pattern Matching

Sei e ein Ausdruck, p ein Pattern, v eine neue Variable, b ein BoolescherAusdruck, und qs wieder eine Sequenz von Qualifiern.

J[ e | p <- xs, qs ]K = concatMap(λv . case v of

p → J[ e | qs ]K_→ []

)JxsK

1○

J[ e | b, qs ]K = if JbK then J[ e | qs ]K else [] 2○

J[ e | ]K = [ JeK ] 3○

JeK = Wende J·K rekursiv auf alle nicht-primitivenTeilausdrucke von e an.

4○

I Variable v matcht gegen jeden Wert aus JxsK (cf. Seite 151),

I case pruft dann ob v auf Pattern p matcht (cf. Seite 157),

I fur fehlgeschlagene Matches werden keine Ergebnisse erzeugt.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 254

Page 255: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Beispiel Nochmal: heads xs = [ y | (y:_) <- xs ]

Ubersetzen heads mit dem Ubersetzungsschema J·K:

Jλxs. [ y | (y:_) <- xs ]K= 4○

λxs. J[ y | (y:_) <- xs ]K= 1○, diesmal richtig

λxs. concatMap(λv . case v of

(y:_)→ J[ y | ]K_→ []

)JxsK

= 3○, 1○

λxs. concatMap(λv . case v of { (y:_)→ [y]; _ → [] }

)xs

]η concatMap

(λv . case v of { (y:_)→ [y]; _→ [] }

)Jetzt gilt:heads ≡ concatMap

(λv . case v of { (y:_)→ [y]; _→ [] }

)Stefan Klinger · DBIS Informatik 2 · Sommer 2016 255

Page 256: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

8 · Listenverarbeitung List Comprehensions · 8.5

Weiterfuhrende Literatur

Richard Bird, and Philip Wadler.Introduction to Functional Programming using Haskell.Prentice Hall International, Series in Computer Science, 1998.

Jeroen, Fokker.Functional Programming.Department of Computer Science, Utrecht University, 1995.http://www.staff.science.uu.nl/~fokke101/courses/fp-eng.pdf

Torsten Grust, and Marc H. Scholl.How to Comprehend Queries Functionally.Journal of Intelligent Information Systems, vol. 12, p. 191–218, 1999.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 256

Page 257: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9Algebraische Datentypen

Page 258: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen

Dieses Kapitel erweitert Haskells Typsystem, das neben BasistypenInteger, Float, Char, Bool, ...) und den Typkonstruktoren ([ · ], (,)...und ->) auch algebraische Datentypen kennt.

I Ganz analog zum Typkonstruktor [ · ], der die beidenKonstruktorfunktionen (:) und [] einfuhrte, um Werte des Typs [α]zu konstruieren, kann der Programmierer neue Konstruktorendefinieren, um Werte eines neuen algebraischen Datentyps zu erzeugen.

I Wie bei Listen und Tupeln moglich, konnen Werte dieser neuen Typendann mittels Pattern Matching wieder analysiert (dekonstruiert)werden.

In der Tat ist der eingebaute Typkonstruktor [α] selbst ein algebraischerDatentyp (s. unten).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 258

Page 259: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Deklaration eines algebraischen Datentyps · 9.1

9.1 Deklaration eines algebraischen Datentyps

Mittels einer data-Deklaration wird ein neuer algebraischer Datentypspezifiziert mit:I dem NamenT des Typkonstruktors (Identifier beginnend mit Zeichen∈ {A...Z}) und seinen Typparametern αj ,

I den Namen Ki der Konstrukturfunktionen (Identifier beginnend mitZeichen ∈ {A...Z}) und der Typen βik , die diese als Parameter erwarten.

Syntax einer data-Deklaration

mit n ≥ 0,m ≥ 1, ni ≥ 0, die βik sind entweder Typbezeichner oder βik = αj :

data T α1 α2 ... αn = K1 β11 ... β1n1

| K2 β21 ... β2n2

...| Km βm1 ... βmnm

Dieses data-Statement deklariert einen Typkonstruktor T und mKonstruktorfunktionen:

Ki :: βi1 → ...→ βini → T α1 α2 ... αnStefan Klinger · DBIS Informatik 2 · Sommer 2016 259

Page 260: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Deklaration eines algebraischen Datentyps · 9.1

Sonderfalle

1. Die Ki haben keine Argumente, also ni = 0, n = 0.

data T = K1 | K2 | · · · | Km

T ist damit ein reiner Summentyp (auch: Aufzahlungstyp) wie ausvielen Programmiersprachen bekannt (etwa in C: enum).

• Die Konstruktoren haben alle den gleichen Typ, und bilden den Wertevorratvon T :

Ki :: T

• Der Typ Bool ist ein Aufzahlungstyp:

data Bool = False | True

• Dies gilt theoretisch ebenso fur die anderen Basisdatentypen in HaskellsTypsystem:

1 data Int = -2^63 | ... | -1 | 0 | 1 | ... | 2^63-1 — Pseudo-Code!2 data Char = ’a’ | ’b’ | ... | ’A’ | ... | ’1’ | ...

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 260

Page 261: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Deklaration eines algebraischen Datentyps · 9.1

2. Es gibt nur eine Konstruktorfunktion, also m = 1, β1i = αi .

data T α1 ... αn = K1 α1 ... αn

T verhalt sich damit ahnlich wie der Tupelkonstruktor und wird auchProdukttyp genannt. In der Typtheorie oft als β11 × β12 × · · · × β1n1

notiert.• Die (fest eingebauten) Definitionen von Tupeln entsprechen also:

data (α,β) = (,) α β

data (α,β,γ) = (,,) α β γ

Allgemein fuhrt die data-Deklaration also Alternativen (Summe) vonProdukttypen ein, bezeichnet als sum-of-product types.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 261

Page 262: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Deklaration eines algebraischen Datentyps · 9.1

Arbeiten mit Aufzahlungstypen

Beispiel Der benutzerdefinierte Aufzahlungstyp

data Weekday = Mon | Tue | Wed | Thu | Fri | Sat | Sun

definiert

I den Typkonstruktor Weekday und

I die Konstruktorfunktionen Mon, ..., Sun mit z.B. Mon :: Weekday.

Funktionen uber algebraischen Datentypen werden mittels PatternMatching realisiert:

1 weekend :: Weekday -> Bool

2 weekend Sat = True

3 weekend Sun = True

4 weekend _ = False

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 262

Page 263: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Deklaration eines algebraischen Datentyps · 9.1

Ausgabe von Aufzahlungstypen

Bei der Arbeit mit diesen neuen Typen reagiert Haskell merkwurdig:

1 *Main> Mon

2 <interactive>:7:1:

3 No instance for (Show Weekday) arising from a use of ‘print’

4 In a stmt of an interactive GHCi command: print it

5 *Main> Tue == Fri

6 <interactive>:8:5:

7 No instance for (Eq Weekday) arising from a use of ‘==’

8 In the expression: Tue == Fri

9 In an equation for ‘it’: it = Tue == Fri

1. Das Haskell-System hat keine Methode show fur die Ausgabe vonWerten des Typs Weekday mitgeteilt bekommen.• Intuition: Name des Konstruktors Ki benutzen.

2. Gleichheit auf den Elementen des Typs ist nicht definiert.• Intuition: nur Werte die durch denselben Konstruktor Ki mit identischen

Parametern erzeugt wurden, sind gleich.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 263

Page 264: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Deklaration eines algebraischen Datentyps · 9.1

I Haskell kann diese Intuitionen automatisch zur Verfugung stellen,wenn die data-Deklaration durch den Zusatz

deriving (Show, Eq)

erweitert wird.

1 data Weekday = Mon | Tue | Wed | Thu | Fri | Sat | Sun

2 deriving (Show, Eq)

I Der neue Typ T wird damit automatisch Instanz der Typklasse Show allerdruckbaren Typen und Instanz der Typklasse Eq aller Typen mitGleichheit (==).

I Der deriving-Mechanismus ist genereller und wird spater noch genauerbesprochen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 264

Page 265: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Deklaration eines algebraischen Datentyps · 9.1

Maybe an Integer?

Algebraische Datentypen erlauben die Erweiterung eines Typs um einenspeziellen Wert, der eingesetzt werden kann, wenn Berechnungen keinsinnvolles oder ein unbekanntes Ergebnis besitzen.

Beispiel Erweitere den Typ Integer um einen “Fehlerwert” None:

1 data MaybeInt = Val Integer

2 | None

3 deriving (Show, Eq)

4

5 safediv :: Integer -> Integer -> MaybeInt

6 safediv _ 0 = None

7 safediv x y = Val (x ‘div‘ y)

Fragen

I Was sind in diesem Beispiel Konstruktorfunktionen?

I Wie lautet jeweils ihr Typ?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 265

Page 266: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Deklaration eines algebraischen Datentyps · 9.1

Maybe α

I Der vordefinierte Typkonstruktor Maybe kann jeden Typ um das ElementNothing erweitern.

data Maybe α = Just α| Nothing

deriving (Eq, Show)

I Der Typkonstruktor ist polymorph (wie etwa auch [α]):

Beispiel Erweitere den Typ Integer um einen “Fehlerwert” Nothing:

1 safediv :: Integer -> Integer -> Maybe Integer

2 safediv _ 0 = Nothing

3 safediv x y = Just (x ‘div‘ y)

Fragen

I Welchen Typ konstruiert der Typkonstruktor? Woraus?

I Was sind die Typen der Konstruktorfunktionen?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 266

Page 267: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Deklaration eines algebraischen Datentyps · 9.1

entweder-oder: Union Types

I Ein Union Type (vgl. Cs union oder Pascals “variant records”) kannals algebraischer Datentyp dargestellt werden.

Beispiel In der Prelude ist bereits vordefiniert:

data Either α β = Left α| Right βderiving (Eq, Show)

I Die Konstruktoren Left und Right betten Werte der Typen α und β ineinen gemeinsamen Typ Either α β ein, z.B.:

[Left ’x’, Right True, Right False, Left ’y’]

Frage Was sind die Typen der Konstruktorfunktionen? Und was ist der Typder Liste oben?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 267

Page 268: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Deklaration eines algebraischen Datentyps · 9.1

nochmal: data Either α β = Left α| Right βderiving (Eq, Show)

I Beim Pattern-Matching liefern die Konstruktoren Information daruber,von welchem Typ der enthaltene Wert ist.• Genauer: Wie der Wert konstruiert wurde.

Beispiel Was tut die Funktion getLeft?

1 getLeft :: [Either a b] -> [a] — Bessere Implementierung in der Ubung2 getLeft [] = []

3 getLeft (Left a : xs) = a : getLeft xs

4 getLeft (_:xs) = getLeft xs

Frage Was liefert getLeft [Left True, Right "foo", Left "bar"]?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 268

Page 269: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Rekursive algebraische Typen · 9.2

9.2 Rekursive algebraische Typen

I Die interessantesten Konstruktionen lassen sich durch rekursiveTyp-Deklarationen erzielen.

I Damit lassen sich vor allem diverse Arten von Baumen als neue Typenausdrucken.

Beispiel BinTree α — binare Baume uber beliebigem Typ α.

data BinTree α = Empty

| Node (BinTree α) α (BinTree α)deriving (Eq, Show)

I Der Konstruktor Empty steht fur den leeren Baum,

I Node reprasentiert einen Knoten mit linkem Unterbaum,Knotenbeschriftung des Typs α und rechtem Unterbaum.

Frage Was sind die Typen der Konstruktorfunktionen?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 269

Page 270: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Rekursive algebraische Typen · 9.2

I Die Konstruktion eines Binarbaums mit Integer-Knotenlabels ist danneinfach:

1 atree' :: BinTree Integer

2 atree' = Node

3 (Node Empty 1 (Node Empty 0 Empty))

4 2

5 ( Node

6 (Node (Node Empty 3 Empty) 4 Empty)

7 6

8 (Node Empty 7 Empty)

9 )

I atree' reprasentiert den folgenden binaren Baum (ε bezeichnet leereUnterbaume): 2

1

ε 0

ε ε

6

4

3

ε ε

ε

7

ε ε

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 270

Page 271: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Rekursive algebraische Typen · 9.2

I Um die Notation weiter zu vereinfachen, setzen wir eine Funktion leaf

zur Konstruktion von Blattern ein:

1 leaf :: a -> BinTree a

2 leaf x = Node Empty x Empty

I Damit notieren wir atree' kurzer als

1 atree :: BinTree Integer

2 atree = Node

3 (Node Empty 1 (leaf 0))

4 2

5 (Node (Node (leaf 3) 4 Empty) 6 (leaf 7))

I Wegen deriving Eq konnen wir die beiden Baume sogar vergleichen:

1 *Main> atree == atree'2 True

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 271

Page 272: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Rekursive algebraische Typen · 9.2

Listen als algebraischer Datentyp

I Der eingebaute Typkonstruktor [ · ] fur Listen ist, ganz ahnlich wieBinTree, ein rekursiver algebraischer Datentyp. Seine Definitionentspricht

data [α] = []

| α : [α]

I Entgegen der bisherigen Vereinbarungen wird hier der KonstruktorK2 = (:) in Infix-Notation geschrieben.

• Auch fur nutzerdefinierte Konstruktorfunktionen steht dieses Feature zurVerfugung: Ein Konstruktorname der Form

:[!#$%&*+/<=>?@\^|~:.

]∗wird infix verwendet (cf. Seite 133, Syntax der Infix-Operatoren).

• Die Verwendung von eckigen Klammern als Typkonstruktor ist syntaktischerZucker und steht fur nutzerdefinierte Typen nicht zur Verfugung.

Frage Wie definiert man einen Typ fur garantiert nicht-leere Listen?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 272

Page 273: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Rekursive algebraische Typen · 9.2

Rationale Zahlen

Beispiel Mittels Infix-Konstruktoren lasst sich bspw. der hier neudefinierte Typ rationaler Zahlen darstellen:

1 data Frac = Integer :/ Integer

2 deriving Show

3 > 2 :/ 3

4 2 :/ 3 :: Frac

Frage Wieso wird hier nicht auch die Gleichheit mittelsderiving (Show, Eq) abgeleitet?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 273

Page 274: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

9.3 Baume Große und Hohe eines Baumes

I Bei der Analyse von Algorithmen auf Baumen hangt die Laufzeit oft vonder Große (Anzahl der Knoten) und Hohe (Lange des langsten Pfadesvon der Wurzel zu einem Blatt) eines Baumes ab.

I Wir definieren hier die entsprechenden Funktionen size und depth furBinTree, cf. Seite 269.

1 size, depth :: BinTree a -> Integer

2

3 size Empty = 0

4 size (Node l a r) = size l + 1 + size r

5

6 depth Empty = 0

7 depth (Node l a r) = 1 + depth l ‘max‘ depth r

I Beide Funktionen orientieren sich an der rekursiven Struktur des TypsBinTree und sehen je einen Fall fur jeden Konstruktor vor (vgl.Listenverarbeitung).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 274

Page 275: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

Beweise entlang der Struktur algebraischer Datentypen

I Beweise uber Algorithmen auf algebraischen Datentypen verlaufen ganzanalog zu Beweisen von Aussagen uber Listen: mit Induktion uber denAufbau.

Beweisschema

Fur den Typ BinTree α lautet das Schema fur Induktionsbeweise:

1. Induktionsverankerung: leerer Baum Empty,

2. Induktionsschritt: von ` und r zu Node ` a r

Satz

Zwischen der Große und Tiefe eines Binarbaums t besteht der folgendeZusammenhang:

depth t ≤ size t ≤ 2depth t − 1

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 275

Page 276: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

Beweis Wir verwenden Induktion uber die Struktur von t zum Beweis derzweiten Aussage:

size t ≤ 2depth t − 1

Induktionsverankerung Empty

size Empty

= size.1

0

= einfache Arithmetik

20 − 1

= depth.1

2depth Empty − 1

Falls wir die Begrundung einfacheArithmetik nicht akzeptieren, konnenwir arithmetische Operationen durchHaskell-Aquivalente ersetzen(bspw. ab durch power a b), undderen Definition im Beweisverwenden.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 276

Page 277: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

Induktionshypothese Seien `, r :: BinTree α, fest, beliebig, mit

size ` ≤ 2depth ` − 1 und size r ≤ 2depth r − 1

Induktionsschritt von ` und r zu Node ` a r

size (Node ` a r)

= size.2

size `+ 1 + size r

≤ Induktionshypothese

(2depth ` − 1) + 1 + (2depth r − 1)

= Arithmetik

2depth ` + 2depth r − 1

≤ a ≤ a ‘max‘ b

2 · (2depth ` ‘max‘ 2depth r )− 1

= a ≤ b ⇒ 2a ≤ 2b

2 · 2depth ` ‘max‘ depth r − 1

= Arithmetik

21+depth ` ‘max‘ depth r − 1

= depth.2

2depth (Node ` a r) − 1

Wichtig: Tatsachlich verwenden wir hier zwei Induktionshypothesen, einefur ` und eine fur r . �

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 277

Page 278: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

Linkester Knoten eines Binarbaumes

Problem Suche den Wert des Knotens “links außen”.

I Dies kann nicht immer ein sinnvolles Ergebnis liefern: Ein leerer Baumhat keinen linkesten Knoten.

I Nutze daher den algebraischen Typkonstruktor Maybe.

leftmost :: Bintree α -> Maybe α

1 leftmost :: BinTree α -> Maybe α2 leftmost Empty = Nothing

3 leftmost (Node Empty a r) = Just a

4 leftmost (Node l a r) = leftmost l

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 278

Page 279: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

Nochmal:

1 leftmost :: BinTree α -> Maybe α2 leftmost Empty = Nothing

3 leftmost (Node Empty a r) = Just a

4 leftmost (Node l a r) = leftmost l

Alternative Losung leftmost’

I steigt zuerst rekursiv in den Baum ab, und

I propagiert einen evtl. linkesten Knoten (Just b) nach oben bzw.

I gibt den aktuell linkesten Knoten zuruck (Just a), wenn der linkerUnterbaum leer ist.

1 leftmost’ :: BinTree α -> Maybe α2 leftmost’ Empty = Nothing

3 leftmost’ (Node l a r) = case leftmost’ l of

4 Nothing -> Just a

5 Just b -> Just b

Frage Welche Variante ist besser?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 279

Page 280: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

Nochmal:

1 leftmost :: BinTree α -> Maybe α2 leftmost Empty = Nothing

3 leftmost (Node Empty a r) = Just a

4 leftmost (Node l a r) = leftmost l

5

6 leftmost’ :: BinTree α -> Maybe α7 leftmost’ Empty = Nothing

8 leftmost’ (Node l a r) = case leftmost’ l of

9 Nothing -> Just a

10 Just b -> Just b

Frage Welche Variante ist besser?

Antwort leftmost ist endrekursiv und kann deshalb in konstantem Platzausgewertet werden. Dagegen baut leftmost’ eine Sequenz auscase-Ausdrucken auf und benotigt linearen Platz.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 280

Page 281: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

I Die folgende Variante bestimmt das Element links außen, gibt abergleichzeitig den Baum zuruck, der bei dessen Entfernung entsteht:

splitleftmost'

3

1

ε 2

ε ε

4

ε ε_

3

2

ε ε

4

ε ε

1 splitleftmost’ :: BinTree α -> Maybe (α, BinTree α)2 splitleftmost’ Empty = Nothing

3 splitleftmost’ (Node l a r) = case splitleftmost’ l of

4 Nothing -> Just (a, r)

5 Just (a’,l’) -> Just (a’, Node l’ a r)

Ubung splitleftmost’ orientiert sich an dem Rekursionsschema furleftmost’ und nicht an dem fur leftmost. Die ganze Arbeit beimrekursiven Abstieg in den Baum zu leisten ist schwieriger. Wie konnte eineendrekursive Variante splitleftmost implementiert werden?

~

Nicht ganz einfach.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 281

Page 282: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

Linearisierung von Baumen

Dieser Abschnitt befasst sich mit der Uberfuhrung von Baumen inListen von Knotenmarkierungen. Man unterscheidet:

Tiefendurchlauf aka. DFS, depth-first search

I Folgt der rekursiven Struktur der Baume und ist vergleichsweise simpelzu implementieren.

I Je nachdem, ob man die Markierung eines Knotens vor (→ Preorder),zwischen (→Inorder) oder nach (→ Postorder) der Linearisierungseiner Teilbaume ausgibt, erhalt man verschiedene Tiefendurchlaufe.

Breitendurchlauf aka. BFS, breadth-first search

I Zahlt die Knoten ebenenweise von der Wurzel ausgehend auf. Dienachste Ebene wird erst nach Aufzahlung der daruber liegendenabgearbeitet.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 282

Page 283: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

Tiefendurchlaufe

1 inorder :: BinTree a -> [a]

2 inorder Empty = []

3 inorder (Node l a r) = inorder l ++ [a] ++ inorder r

Frage Wie lauten die Gleichungen fur Preorder und Postorder?

Beispiel inorder atree_ [1,0,2,3,4,6,7].

~

Die Effizienz von inorder wird durch die Laufzeit derListenkonkatenation ++ bestimmt, die linear im ersten Argument ist. Derworst-case fur inorder ist somit ein linksentarteter Baum.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 283

Page 284: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

Linkstiefer Baum

I Die Funktion leftist erzeugt einen linksentarteten Baum aus einer Listevon vorgegebenen Knotenmarkierungen:

1 leftist :: [α] -> BinTree α2 leftist [] = Empty

3 leftist (x:xs) = Node (leftist xs) x Empty

I Aufgrund der Laufzeit von ++ benotigt inorder (leftist [1..n])eine Laufzeit in O(n2).

Ubung: Fur inorder lasst sich eine Implementation finden, die linear in nist. Die Losung orientiert sich an der Idee zur Beschleunigung von reverse,cf. Seite 224.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 284

Page 285: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

Breitendurchlauf

I Wir setzen eine Hilfsfunktion traverse ein, die eine Liste ts vonTeilbaumen (einer Ebene) erhalt, und deren Knoten entsprechendaufzahlt:

1 traverse :: [BinTree α] -> [α]2 traverse [] = []

3 traverse ts = roots ts ++ traverse (childs ts)

I Einen Breitendurchlauf erhalten wir dann einfach mittels

1 levelorder :: BinTree α -> [α]2 levelorder t = traverse [t]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 285

Page 286: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

I Es fehlen lediglich noch die Funktionen roots zur Bestimmung allerWurzeln bzw. childs zur Bestimmung aller Teilbaume einer Liste vonBaumen:

1 roots :: [BinTree α] -> [α]2 roots [] = []

3 roots (Empty : ts) = roots ts

4 roots (Node _ a _ : ts) = a : roots ts

5

6 childs :: [BinTree α] -> [BinTree α]7 childs [] = []

8 childs (Empty : ts) = childs ts

9 childs (Node l _ r : ts) = l : r : childs ts

I Mit List Comprehension lassen sich beide Funktionen elegant als Einzeilerrealisieren:

1 roots ts = [ a | Node _ a _ <- ts ]

2 childs ts = [ t | Node l _ r <- ts, t <- [l, r] ]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 286

Page 287: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

fold uber Baumen

Das allgemeine Rekursionsschema foldr uber Listen (cf. Seite 207) lasstsich auch auf anders konstruierte algebraische Datentypen ubertragen.

I foldr (⊕) z xs ersetzt in der Liste xs die Listenkonstruktoren : und []durch ⊕ bzw. durch z .

I Analog lasst sich eine Funktion tfold (tree fold) uber BinTreesdefinieren:

1 tfold' :: (β -> α -> β -> β) -> β -> BinTree α -> β2 tfold' f z Empty = z

3 tfold' f z (Node l a r) = f (tfold' f z l) a (tfold' f z r)

I Der Effekt von tfold auf atree (cf. Seite 270) ist damit etwa:

tfold f z

2

1

ε 0

ε ε

6

4

3

ε ε

ε

7

ε ε

_

f 2

f 1

z f 0

z z

f 6

f 4

f 3

z z

z

f 7

z z

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 287

Page 288: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

Das go-Idiom34

I Funktionen wie tfold’ reichen ihre Argumente f und z unverandert anden rekursiven Aufruf weiter. Nochmal der Code von der vorigen Folie:

1 tfold' :: (β -> α -> β -> β) -> β -> BinTree α -> β2 tfold' f z Empty = z

3 tfold' f z (Node l a r) = f (tfold' f z l) a (tfold' f z r)

• Das Weiterreichen von f und z verursacht unnotigen Aufwand.• Fur den Programmierer ist dieser Umstand nur schwer zu erkennen.

I Eleganter ist es, dies im Code explizit auszudrucken:• Ersetzen den konstanten Teil tfold' f z durch go:

1 tfold :: (β -> α -> β -> β) -> β -> BinTree α -> β2 tfold f z = go — η-Konversion: tfold f z tree = go tree

3 where

4 go Empty = z

5 go (Node l a r) = f (go l) a (go r)

• Aus Sicht der lokalen Definition von go sind f und z freie Variablen.• Nur der veranderliche Parameter wird von go in der Rekursion

weitergegeben.34Don Stewart uber die Herkunft: http://stackoverflow.com/a/5844850Stefan Klinger · DBIS Informatik 2 · Sommer 2016 288

Page 289: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Baume · 9.3

AnwendungenI Die Funktionen size und depth auf Baumen konnen mit tfold

implementiert werden:

1 size, depth :: BinTree α -> Integer

2

3 size = tfold (\l _ r -> l + 1 + r) 0 — η-Konversion: size t = tfold (...) 0 t

4 depth = tfold (\l _ r -> 1 + l ‘max‘ r) 0

I Die Tiefendurchlaufe konnen ebenfalls als Instanzen von tfold verstandenwerden:

1 inorder, preorder, postorder :: BinTree α -> [α]2

3 inorder = tfold (\l a r -> l ++ [a] ++ r) []

4 preorder = tfold (\l a r -> [a] ++ l ++ r) []

5 postorder = tfold (\l a r -> l ++ r ++ [a]) []

I Schließlich ist auch leftmost' mittels tfold ausdruckbar:1 leftmost' :: BinTree α -> Maybe α2 leftmost' = tfold f Nothing

3 where

4 f Nothing a _ = Just a

5 f other _ _ = other — other matcht (Just _)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 289

Page 290: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Allgemein: Fold uber Algebraische Datentypen · 9.4

9.4 Allgemein: Fold uber Algebraische Datentypen

Beispiel Betrachten wir nochmal Either von Folie 267:

Die Definition...1 data Either α β = Left α2 | Right β

...erzeugt die Konstruktoren

1 Left :: α -> Either α β2 Right :: β -> Either α β

I Die Konstruktoren reprasentieren die verschiedenen Moglichkeiten,ihre jeweiligen Argumente in einen gemeinsamen Typ einzubetten.

• [Left True, Right ’c’] ist eine homogene Liste!

I Mochte man Either α β auf einen anderen Typ γ abbilden, so mussman sich fur jede dieser Moglichkeiten uberlegen, wie man zu einem γkommt:

• Um eine Funktion vom Typ Either α β → γ zu konstruieren...• brauchen wir eine Funktion f :: α→ γ, ... (fur mit Left eingebettete Werte)

• und eine Funktion g :: β → γ. (fur mit Right eingebettete Werte)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 290

Page 291: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Allgemein: Fold uber Algebraische Datentypen · 9.4

I Gesucht: Funktion fromEither' :: Either α β → γ .

I Gegeben: f :: α→ γ und g :: β → γ .

I Naturlich konnte man das jetzt direkt ausprogrammieren:

1 f :: Char -> Bool

2 f = (==' ')3

4 g :: Int -> Bool

5 g = (<3)

6

7 fromEither' (Left x) = f x

8 fromEither' (Right y) = g y

Fragen Was ist der Typ von fromEither'? Wo liegt hier eineEinschrankung?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 291

Page 292: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Allgemein: Fold uber Algebraische Datentypen · 9.4

Antwort fromEither' :: Either Char Int→ Bool

Fur jeden anderen Zieltyp, anderes f oder anderes g mussen wir dieFallunterscheidung nochmal programmieren!

I Das Schema von fromEither’ ist so simpel (und wird so oft gebraucht),dass wir von f und g abstrahieren:

1 fromEither f g (Left x) = f x

2 fromEither f g (Right y) = g y

• Das nennen wir dann den Fold uber Either α β.

Frage Was ist der Typ von fromEither ?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 292

Page 293: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Allgemein: Fold uber Algebraische Datentypen · 9.4

I fromEither ist unter dem Namen either in der Prelude vordefiniert:

1 either :: (α -> γ) -> (β -> γ) -> Either α β -> γ2 either f g (Left x) = f x

3 either f g (Right y) = g y

4

5 *Main> either (*2) head $ Left 42

6 84

7 *Main> either (*2) head $ Right [0,8,15]

8 0

I Ein Fold fur Either konsumiert also fur Left und Right jeweils eineFunktion (f und g) ...

I ... und wendet automatisch die richtige auf sein Argument vom TypEither α βan.

⇒ Wir mussen die Fallunterscheidung nicht jedes Mal ausprogrammieren!

I In der Definition von either sieht man direkt wie die Konstruktorendurch f bzw. g ersetzt werden.

Frage Was ist either Left Right ?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 293

Page 294: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Allgemein: Fold uber Algebraische Datentypen · 9.4

Beispiele

I Der Fold uber Maybe heißt maybe:

1 data Maybe α = Nothing

2 | Just α3

4 maybe :: β -> (α -> β) -> Maybe α -> β5 maybe d f Nothing = d

6 maybe d f (Just x) = f x

7

8 *Main> maybe 0 (*7) $ safediv' 18 9 — Ergebnis? (safediv' auf Folie 266)9 *Main> maybe 0 (*7) $ safediv' 18 0 — ...und hier?

I Der Fold uber Paare heißt uncurry:

1 data (α,β) = (,) α β2

3 uncurry :: (α -> β -> γ) -> (α, β) -> γ4 uncurry f (x,y) = f x y

5

6 *Main> uncurry (*) (2,3)

7 6

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 294

Page 295: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Allgemein: Fold uber Algebraische Datentypen · 9.4

AllgemeinI Erinnerung: Die data-Deklaration (cf. Seite 259) definiert die

Konstruktorfunktionen Ki fur den algebraischen Datentyp T α1 ... αn:

data T α1 ... αn = K1 β11 ... β1n1

| ...| Km βm1 ... βmnm

I Um T α1 ... αn auf einen Typ γ abzubilden, brauchen wir fur jedenKonstruktor Ki eine Funktion fi :: βi1 → ...→ βini → γ die seineArgumente auf den gemeinsamen Ergebnistyp γ abbildet.

I Die Funktion foldT :: (β11 → ...→ β1n1 → γ)→ ...→ (βm1 → ...→ βmnm → γ)→ T α1 ... αn

→ γ

soll dann je nach Konstruktor Ki die passende Funktion fi auswahlen.

I Wir mussen foldT passend zum algebraischen Datentyp konstruieren.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 295

Page 296: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Allgemein: Fold uber Algebraische Datentypen · 9.4

Frage Was ist der Fold uber Bool?

1 data Bool = True | False

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 296

Page 297: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Allgemein: Fold uber Algebraische Datentypen · 9.4

Fold uber rekursive algebraische Datentypen

I Fur einfache35 rekursive Datentypen T α1 ... αn taucht bei(mindestens) einer Konstruktorfunktion der konstruierte Typ alsArgument auf:

Ki :: ...→ T α1 ... αn → ...︸ ︷︷ ︸Argumente des Konstruktors Ki

→ T α1 ... αn︸ ︷︷ ︸konstruierterTyp

• Beispiel: Listen-Konstruktor cons: (:) :: α→ [α]→ [α] .

I Die entsprechende Argumentfunktion fi von foldT hat also den Typ

fi :: ...→ γ → ...→ γ~

Obacht Das Argument vom Typ γ stammt aus einem rekursivenAufruf von foldT .

1 foldr :: (α -> β -> β) -> β -> [α] -> β2 foldr (#) z = go — η-Konversion: foldr (#) z xs = go xs

3 where

4 go [] = z

5 go (x:xs) = x # go xs — Hier ist foldr rekursiv!

35Komplexer: T taucht mit anderen Typ(variabl)en im Typ von Ki auf — behandeln wir hier nicht.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 297

Page 298: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

9 · Algebraische Datentypen Allgemein: Fold uber Algebraische Datentypen · 9.4

Beispiel

1 data BinTree α = Empty

2 | Node (BinTree α) α (BinTree α)3

4 tfold :: (β -> α -> β -> β) -> β -> BinTree α -> β5 tfold f z = go — η-Konversion: tfold f z tree = go tree

6 where

7 go Empty = z

8 go (Node l a r) = f (go l) a (go r) — Hier steckt die Rekursion

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 298

Page 299: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10Typklassen und Overloading

Page 300: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Parametrische Polymorphie · 10.1

10.1 Parametrische Polymorphie

Viele der bisher betrachteten Funktionen waren polymorph36, d.h. der Typdieser Funktionen enthielt mindestens eine Typvariable (α, β, ...):

1 id :: α -> α2 snd :: (α,β) -> β3 length :: [α] -> Int

4 take :: Int -> [α] -> [α]5 foldr :: (α -> β -> α) -> α -> [β] -> α6 levelorder :: BinTree α -> [α]

I Mit einer einzigen Funktionsdefinition wird eine Vielzahl “konkreter”Funktionen “definiert”, je eine fur jede gultige Belegung der Typvariablen.

I Das geht nur, insofern die Funktionsweise unabhangig vom Typ derArgumente definiert werden kann.• fst :: (α, β)→ α —Das Argument muss ein Paar sein, und der Typ der

ersten Komponente entspricht dem Ergebnistyp. Die konkreten Typen derKomponenten sind jedoch irrelevant.

I Jede Typvariable kann mit einem beliebigen Typ (konsistent)“instanziiert” werden.

36“Polymorphie” = VielgestaltigkeitStefan Klinger · DBIS Informatik 2 · Sommer 2016 300

Page 301: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Parametrische Polymorphie · 10.1

Man sagt daher auch, die Typvariablen polymorpher Funktionen sindallquantifiziert. Dann liest sich der Typ von foldr wie

foldr :: ∀α. ∀β. (α→ β → α)→ α→ [β]→ α

Funktionen dieser Art werden parametrisch polymorph genannt.

Beispiel In take 3 "foo" und take 10 [0..] wird jeweils die gleicheFunktionsdefinition von take angewandt:

1 take :: Int -> [α] -> [α]2 take n (x:xs) | n > 0 = x : take (n-1) xs

3 take _ _ = []

I Fur den Fall take 3 "foo" : α = Char

und damit etwa [] :: [Char] und (:) :: Char→ [Char]→ [Char],

I Fur den Fall take 10 [0..] : α = Int

und daher [] :: [Int] und (:) :: Int→ [Int]→ [Int].

take ist parametrisch polymorph, take :: ∀α. Int→ [α]→ [α].

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 301

Page 302: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Parametrische Polymorphie · 10.1

Beispiel Die Identitatsfunktion id = λx . x ist auf Argumente beliebigerTypen α anwendbar.

I In den drei Ausdrucken

id 3 = 3

id ’a’ = ’a’

id (3,’a’) = (3,’a’)

wurde id als Funktion der Typen• Integer→ Integer,• Char→ Char und• (Integer, Char)→ (Integer, Char)

benutzt.

I Damit lautet die vollstandige Typisierung von id

id :: ∀α. α→ α

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 302

Page 303: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Parametrische Polymorphie · 10.1

Vorsicht Haskell notiert die Allquantifizierung von Typvariablen nicht:

1 Prelude> :t id

2 id :: a -> a — Eigentlich: ∀α. α→ α3 Prelude> :t take

4 take :: Int -> [a] -> [a] — Eigentlich: ∀α. Int→ [α]→ [α]

Alle Typvariablen sind implizit universell quantifiziert.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 303

Page 304: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Parametrische Polymorphie · 10.1

Eine konkrete Instanz des polymorphen Typs von id (bspw. beiAnwendung auf das Argument (3,’a’) bzw. length) erhalt man durch diekonsistente Subsitution von Typvariablen durch einen (konkreten) Typ.

Beispiel Selbst innerhalb eines Ausdrucks konnen durchaus verschiedeneInstanziierungen desselben polymorphen Objektes auftreten. In

id length $ id [True, True, False]

tritt id :: ∀α. α→ α in den Instanziierungen

α = [Bool] also id :: [Bool]→ [Bool]α = [Bool]→ Int also id :: ([Bool]→ Int)→ ([Bool]→Int)

auf.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 304

Page 305: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Parametrische Polymorphie · 10.1

Frage Kann eine Funktion vom Typ ∀α. α→ α ihr Argument um 1erhohen?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 305

Page 306: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Ad-Hoc Polymorphie (Overloading) · 10.2

10.2 Ad-Hoc Polymorphie (Overloading)37

Eine andere Art von Polymorphie versteckt sich hinter dem Konzept desOverloading:

I Ein einzelnes syntaktisches Objekt (Operator, Funktionsname, ...) stehtfur verschiedene – aber “semantisch ahnliche” – Definitionen.

Beispiel Typische uberladene Funktionen und Operatoren.

(==), (<=) Gleichheit und Ordnung lassen sich fur eine ganzeKlasse von Typen sinnvoll definieren.

(*), (+) Arithmetische Ausdrucke uber ganzen Zahlen undFließkommazahlen werden mit identischen Operator-symbolen notiert.

show, read Fur eine ganze Klasse von Typen lassen sich sinnvolleexterne Reprasentationen (als String) angeben.

37Ad hoc, lat. zu diesem, hierfur, in der Bedeutung von zur Sache passend.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 306

Page 307: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Ad-Hoc Polymorphie (Overloading) · 10.2

Beobachtungen:

I Ohne Overloading waren Funktionsnamen wie equalInt undequalBool, oder showDouble und showBinTree notwendig.

I Fur den Typ BinTree α muss show offensichtlich vollkommen andersimplementiert sein, als fur Double.

Offensichtliche Frage Welchen Typ besitzt (==)? Gilt hier wirklich

(==) :: ∀α. α→ α→ Bool ?

Warum wird Overloading auch “Ad-Hoc Polymorphie” genannt?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 307

Page 308: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Typklassen · 10.3

10.3 Typklassen

I Eine Typklasse (type class) deklariert eine Familie von Funktionen, diefur verschiedene konkrete Typen (sog. Instanzen der Klasse) jeweilsverschieden implementiert werden konnen.

I Die Klasse legt nur den polymorphen Typ der Funktionen fest. DieImplementation erfolgt dann bei der Instanziierung (oder cf. Seite 316).

Syntax & Semantik der Klassendefinition: (Vorlaufig, cf. Seite 319)

class C α where

f1 :: τ1...

fn :: τn

I Ein Typ α kann zu einer Instanzder Klasse C erklart werden...

I ...indem die Funktionen fi :: τiimplementiert werden.

I Hier wird die Klasse C definiert, die Funktionen fi werden deklariert!

I Die Typen τi mussen die Typvariable α enthalten.

I Der Klassenname C muss mit einem Zeichen ∈ [A..Z] beginnen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 308

Page 309: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Typklassen · 10.3

Beispiel Typen, fur deren Werte Tests auf Gleichheit sinnvoll sind,konnen die Operatoren der Klasse Eq (equality) uberladen:

1 class Eq α where

2 (==) :: α -> α -> Bool

3 (/=) :: α -> α -> Bool

I Hier wird die Klasse Eq definiert.

I Die (noch nicht definierten) Funktionen == und /= mussen fur einenkonkreten Typen T implementiert werden.

I Diese Implementierungen fur ein konkretes T haben dann entsprechendden Typ T → T → Bool.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 309

Page 310: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Typklassen · 10.3

Beispiel Typen, deren Werte aufzahlbar sind, konnen die Funktionen derKlasse Enum uberladen ...

1 class Enum α where

2 succ :: α -> α3 pred :: α -> α4 toEnum :: Int -> α5 fromEnum :: α -> Int

6 enumFrom :: α -> [α]7 enumFromThen :: α -> α -> [α]8 enumFromTo :: α -> α -> [α]9 enumFromThenTo :: α -> α -> α -> [α]

...und dann von synaktischem Zucker wie

I [x..] ≡ enumFrom x oder

I [x..y] ≡ enumFromTo x y

Gebrauch machen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 310

Page 311: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Typklassen · 10.3

Type Constraints

I Jetzt ist klarer, welchen Typ z.B. (==) wirklich besitzt:

Fur alle Typen α, welche samtliche Operationen der Typklasse Eq

implementieren, gilt (==) :: α→ α→ Bool .

I Eine Typklasse C kann also als Pradikat auf Typen verstanden werden.• Das Pradikat ist erfullt, wenn alle Funktionen der Klasse fur diesen Typ

implementiert sind.• Das druckt die zugehorige Haskell-Syntax mit einem Type Constraint

(aka. Type Context) klar aus:

fi :: C α ⇒ τi

Hier also:• (==) :: Eq α ⇒ α -> α -> Bool

Obacht Die Typvariable α (also der Parameter von C ), ist in den Typenτi der Klassenfunktionen nicht allquantifiziert!

I Es tauch tatsachlich kein ∀α im polymorphen Typ von fi auf.I Typklassen beschranken (kontrollieren) also die Polymorphie.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 311

Page 312: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Typklassen · 10.3

InstanziierungI Die Zugehorigkeit eines Typs α zu einer Typklasse C wird Haskell

mittels einer instance-Erklarung angezeigt.I Danach gilt der Type Constraint C α ⇒ ... als erfullt.

Syntax der Instanziierung eines Typs zur Klasse C : (vorlaufig, cf. Seite 319)

instance C α where

f1 = Definition von f1...

fn = Definition von fn

I Hier werden die Funktionen fi definiert.I Die Typen der fi durfen nicht nochmal angegeben werden. Sie wurden

bereits bei der Definition der Klasse C deklariert.

Beispiel Werte des Typs Bool erlauben Test auf Gleichheit.1 instance Eq Bool where

2 x == y = (x && y) || (not x && not y)

3 x /= y = not (x == y)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 312

Page 313: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Typklassen · 10.3

Beispiel Vergleiche auf Basistypen werden aus Effizienzgrunden auf denentsprechenden primitiven Gleichheitstest der unterliegenden Maschinezuruckgefuhrt.

Denkbar waren z.B.:

1 instance Eq Char where

2 x == y = primEqChar x y

3 x /= y = not (x == y)

4

5 instance Eq Int where

6 x == y = primEqInt x y

7 x /= y = not (x == y)

8 instance Eq Integer where

9 x == y = primEqInteger x y

10 x /= y = not (x == y)

11

12 instance Eq Float where

13 x == y = primEqFloat x y

14 x /= y = not (x == y)

I Die genannten Funktionen (primEq...) sind dann einImplementationsdetail der Standardbibliothek.

I Der Programmierer muss sich nicht darum kummern, und hat auch meistkeinen Zugriff darauf.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 313

Page 314: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Typklassen · 10.3

Type Constraints in Intanziierungen

I Gleichheit von Listen des Typs [α] ist offensichtlich nur dannwohldefiniert, wenn auch α Gleichheitstests zulasst.

I Dies kann durch einen Type Constraint auf dem Klassenparameter αausgedruckt werden:

1 instance Eq α => Eq [α] where

2

3 [] == [] = True

4 (x:xs) == (y:ys) = x == y && xs == ys

5 _ == _ = False

6

7 xs /= ys = not (xs == ys)

~

Die (==)-Operatorenentstammen verschiedenenInstanziierungen.(was ist damit gemeint?)

I Damit sind jetzt automatisch alle Listen uber vergleichbaren Typenvergleichbar (des rechtfertigt die Syntax =>).

Frage Wie konnten Paare des Typs (α,β) fur den Gleichheitstestzugelassen werden?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 314

Page 315: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Typklassen · 10.3

Antwort Die Instanziierung von Eq (α, β) kommt aus der Prelude, undkonnte etwa so aussehen:

1 instance (Eq α, Eq β) => Eq (α, β) where

2

3 (x, y) == (v, w) = x == v && y == w

4

5 p /= q = not (p == q)

I Vergleiche die letzte Zeile mit der Instanziierung von Eq [α].

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 315

Page 316: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Typklassen · 10.3

class Defaults

I Oft sind default-Definitionen fur die Funktionen einer Typklasse sinnvoll(s. Eq und (/=)).

I Eine default-Definition wird innerhalb des class-Konstruktesvorgenommen. Jede Instanz dieser Typklasse “erbt” diese Definition,wenn sie nicht explizit uberschrieben wird.

Beispiel Allgemein bestehteine offensichtliche Beziehungzwischen Gleichheit undUngleichheit.

1 class Eq a where

2 — Minimal complete definition: (==) | (/=)3 (==) :: a -> a -> Bool

4 x == y = not (x /= y)

5

6 (/=) :: a -> a -> Bool

7 x /= y = not (x == y)

I Bei der Instanziierung muss jetzt nur noch (mindestens!) eine derDefinitionen uberschrieben werden.

I Defaults erlauben es konsistentes Verhalten der Funktionen einer Klassenahezulegen (nicht: erzwingen).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 316

Page 317: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Typklassen · 10.3

Beispiel Typen mit Ordnung konnen die Funktionen der Klasse Ord

uberladen: (data Ordering = EQ | LT | GT)

1 class Ord α where

2 compare :: α -> α -> Ordering

3 (<), (<=), (>=), (>) :: α -> α -> Bool

4 max, min :: α -> α -> α5

6 — Minimal complete definition: (<=) | compare7 compare x y | x == y = EQ

8 | x <= y = LT

9 | otherwise = GT

10

11 x <= y = compare x y /= GT

12 x < y = compare x y == LT

13 x >= y = compare x y /= LT

14 x > y = compare x y == GT

15

16 max x y | x >= y = x

17 | otherwise = y

18 min x y | x <= y = x

19 | otherwise = y

Frage Steht hier die “ganze Wahrheit”? Oder haben wir etwas vergessen?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 317

Page 318: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Typklassen · 10.3

Antwort compare verwendet ==, benotigt also einen Eq α Kontext:

1 class Eq α => Ord α where

2 compare :: α -> α -> Ordering

3 (<), (<=), (>=), (>) :: α -> α -> Bool

4 max, min :: α -> α -> α5

6 — Minimal complete definition: (<=) or compare7 compare x y | x == y = EQ — Hierfur brauchen wir Eq α, ...8 | x <= y = LT

9 | otherwise = GT

10

11 x <= y = compare x y /= GT

12 x < y = compare x y == LT — ... hierfur nicht. Warum?13 x >= y = compare x y /= LT

14 x > y = compare x y == GT

15

16 max x y | x >= y = x

17 | otherwise = y

18 min x y | x <= y = x

19 | otherwise = y

I Auch Klassendefinitionen konnen einen Type Constraint aufweisenI Man darf einen Typ nur dann zu Ord instanziieren, wenn er auch

vergleichbar ist!Stefan Klinger · DBIS Informatik 2 · Sommer 2016 318

Page 319: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Typklassen · 10.3

Zusammenfassung der Syntax38

Ein Type Constraint kann mehrere Klassen oder Typvariablen beinhalten:

(==) :: Eq α ⇒ α→ α→ Bool

λx . x + 1 > 3 :: (Num α,Ord α) ⇒ α→ Bool

λx y z . (x + 1, y > z) :: (Num α,Ord β) ⇒ α→ β → β → (α,Bool)

I Formal hat ein Type Constraint also die Form

? TypeConstraint → OneConstraint =>| ( OneConstraint (, OneConstraint)∗ ) =>

OneConstraint → ClassName TypeVariable

I Klassendefinition und Instanziierung konnen Type Constraintsenthalten:

class TypeConstraint? C α where

Deklarationen und Default-Definitionen

instance TypeConstraint? C α where

Definitionen

38Genauer: https://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-750004.3Stefan Klinger · DBIS Informatik 2 · Sommer 2016 319

Page 320: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Instanziierung algebraischer Datentypen · 10.4

10.4 Instanziierung algebraischer Datentypen

Beispiel Erinnerung: Typ Weekday.1 data Weekday = Mon | Tue | Wed | Thu | Fri | Sat | Sun

I Wie macht man Weekday zu einem aufzahlbaren Datentyp (also zu einerInstanz von Enum)?

I Die Prelude definiert39 Defaults fur alle Funktionen in Enum bis auftoEnum und fromEnum:

1 class Enum a where

2 toEnum :: Int -> a

3 fromEnum :: a -> Int

4

.

.

.

5 succ :: a -> a

6 succ = toEnum . (+1) . fromEnum

7

.

.

.

8 enumFromTo :: a -> a -> [a]

9 enumFromTo x y = map toEnum [ fromEnum x .. fromEnum y ]

10

.

.

.

39http://hackage.haskell.org/package/base-4.8.0.0/docs/Prelude.html#t:EnumStefan Klinger · DBIS Informatik 2 · Sommer 2016 320

Page 321: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Instanziierung algebraischer Datentypen · 10.4

Verbleibt also die Definition vontoEnum und fromEnum mit deroffensichtlich gewunschtenEigenschaft fromEnum ◦ toEnum ≡ id.

Hinweis fromEnum und toEnum

etablieren einen Isomorphismus vonWeekday und [0..6].

Jetzt geht zum Beispiel:

1 *Main> [Wed .. Sat] — Leerzeichen wichtig!2 [Wed,Thu,Fri,Sat]

1 instance Enum Weekday where

2 toEnum 0 = Mon

3 toEnum 1 = Tue

4 toEnum 2 = Wed

5 toEnum 3 = Thu

6 toEnum 4 = Fri

7 toEnum 5 = Sat

8 toEnum 6 = Sun

9 fromEnum Mon = 0

10 fromEnum Tue = 1

11 fromEnum Wed = 2

12 fromEnum Thu = 3

13 fromEnum Fri = 4

14 fromEnum Sat = 5

15 fromEnum Sun = 6

Problem Die Definition derartiger Datentypen als Instanz von Enum (aberauch Eq, Ord, Show, Read40) ist kanonisch, aufwandig, und fehleranfallig.

40Einige dieser Typklassen tauchen spater noch auf.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 321

Page 322: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Instanziierung algebraischer Datentypen · 10.4

Beispiel Wir machen BinTree zur Instanz von Eq, und definieren dazuden Gleichheitstest auf Werten von BinTree:

1 instance Eq a => Eq (BinTree a) where

2 Empty == Empty = True

3 Node l1 x1 r1 == Node l2 x2 r2 = x1 == x2 && l1 == l2 && r1 == r2

4 _ == _ = False

Beobachtungen (regulares Muster):

I Die Struktur der Definition von (==) folgt der rekursiven Struktur desDatentyps BinTree.

I Nur jeweils durch gleiche Konstruktoren erzeugte Werte konnenpotentiell gleich sein.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 322

Page 323: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Instanziierung algebraischer Datentypen · 10.4

deriving

I Das soeben beobachtete regulare Muster der Typklassen-Operationenermoglicht es dem Haskell-Compiler, instance-Deklarationenautomatisch abzuleiten.

Syntax Die deriving-Klausel...

data T α1 α2 ... αn = ...| ......deriving (C1,...,Cm)

...macht den Typkonstruktor T zur Instanz der Typklassen C1, ...Cm.

I Diese Magie ist leider nicht fur alle Typklassen Ci verfugbar.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 323

Page 324: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Instanziierung algebraischer Datentypen · 10.4

Die Definitionen der Typklassen-Operationen konnen automatisch erzeugtwerden, fur folgende in der Prelude definierten Klassen:

Eq Ableitbar fur alle Datentypen mit vergleichbaren Komponenten.

I Gleichheit wird uber die Identitat von Konstruktoren und(rekursiv) der Gleichheit der Komponenten des Datentypsentschieden.

Ord Ableitbar fur alle Datentypen mit anordenbaren Komponenten.

I Reihenfolge der Konstruktoren in data-Deklarationentscheidend, Ordnung wird lexikographisch (rekursiv) definiert.

Enum Datentyp muss ein reiner Summentyp sein (s. vorn), also

data T = K0 | ... | Kn−1

mit fromEnum Ki = i .

Show Textuelle Reprasentation der Konstruktoren, s. spater.

... Einige andere die wir hier nicht besprechen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 324

Page 325: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Instanziierung algebraischer Datentypen · 10.4

Beispiel BinTree (nochmal)

1 data BinTree a = Empty

2 | Node (BinTree a) a (BinTree a)

3 deriving (Eq, Ord)

fuhrt automatisch zu:

1 instance Eq a => Eq (BinTree a) where

2 Empty == Empty = True

3 Node l1 x1 r1 == Node l2 x2 r2 = x1 == x2 && l1 == l2 && r1 == r2

4 _ == _ = False

5

6 instance Ord a => Ord (BinTree a) where

7 Empty <= Empty = True

8 Empty <= Node _ _ _ = True

9 Node _ _ _ <= Empty = False

10 Node l1 x1 r1 <= Node l2 x2 r2 = l1 < l2

11 || l1 == l2 && x1 < x2

12 || x1 == x2 && r1 <= r2

Hinweis zu den == Operatoren: Der Type Constraint Ord α impliziertbereits Eq α. Das kommt aus der Klassendefinition von Ord, cf. Seite 318

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 325

Page 326: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Instanziierung algebraischer Datentypen · 10.4

Beispiel Nicht immer ist deriving die Antwort!Erinnerung – Frac reprasentiert rationale Zahlen.

1 data Frac = Integer :/ Integer

2 deriving Eq

Hier fuhrt deriving nicht zum Ziel ...

1 > 2 :/ 5 == 4 :/ 10

2 False

Gemeint ist vielmehr:

1 instance Eq Frac where

2 (x1 :/ y1) == (x2 :/ y2) = x1 * y2 == x2 * y1

3

4 > 2 :/ 5 == 4 :/ 10

5 True

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 326

Page 327: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Instanziierung algebraischer Datentypen · 10.4

Beispiel Weekday (nochmal)

1 data Weekday = Mon | Tue | Wed | Thu | Fri | Sat | Sun

2 deriving (Eq, Ord, Enum, Show)

Damit haben wir automagisch:

1 > Mon < Tue

2 True

3 > Mon == Sat

4 False

5 > [Mon,Wed .. Sun]

6 [Mon,Wed,Fri,Sun]

7 > fromEnum Sat

8 5

~

Frage Was ergibt der Aufruf map toEnum [2,3]?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 327

Page 328: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Anmerkung: Mehrdeutige Typen · 10.5

10.5 Anmerkung: Mehrdeutige Typen

I Die Funktion show :: Show α ⇒ α→ String wird vom GHCiverwendet, um das Ergebnis einer Berechnung auszugeben (cf. Seite 334).

1 *Main> ['1', '2', '3']2 "123"

3 *Main> [1,2,3]

4 [1,2,3]

5 *Main> 123

6 123

1 *Main> show ['1', '2', '3']2 "\"123\""

3 *Main> show [1,2,3]

4 "[1,2,3]"

5 *Main> show 123

6 "123"

I Offensichtlich muss show fur verschiedene Typen unterschiedlichimplementiert sein.⇒ Je nach Typ wird die passende Implementation von show ausgewahlt.

I Welche Implementation soll fur toEnum 2 ausgewahlt werden?

1 *Main> :t toEnum 2

2 toEnum 2 :: Enum a => a

Vollkommen unklar! α kann mit jedembeliebigen Typen aus der Klasse Enum

instanziiert werden.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 328

Page 329: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Anmerkung: Mehrdeutige Typen · 10.5

Fehlermeldung bis GHCi 7.6.3, sonst cf. Seite 332

1 Prelude> toEnum 2

2 <interactive>:2:1:

3 No instance for (Enum a0) arising from a use of ‘toEnum’

4 The type variable ‘a0’ is ambiguous

5 Possible fix: add a type signature that fixes these type variable(s)

6 Note: there are several potential instances:

7 instance Enum Weekday -- Defined at <interactive>:3:35

8 instance Enum Double -- Defined in ‘GHC.Float’

9 instance Enum Float -- Defined in ‘GHC.Float’

10 ...plus 8 others

I Der GHCi sagt uns dass er nicht weisswelches Enum wir meinen.

I Wir konnen aber fur einen Ausdruckexplizit einen Typ angeben:

1 *Main> toEnum 2 :: Ordering

2 GT

3 *Main> toEnum 2 :: Char

4 '\STX' — cf. ascii(7)5 *Main> toEnum 2 :: Weekday

6 Wed

7 *Main> toEnum 2 :: Int

8 21 *Main> :t 4

2 4 :: Num a => a

3 *Main> 4

4 4 Frage Was passiert hier? Warum kein Fehler?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 329

Page 330: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Anmerkung: Mehrdeutige Typen · 10.5

Type Defaulting

Antwort Offensichtlich sucht sich der GHCi einen “passenden Typ” aus.

I Auf Dauer ware es anstrengend, auch bei einfachen Fallen (z.B. Zahlen)immer einen Typ mit angeben zu mussen.

I Dieses Vorgehen heisst TypeDefaulting und wird auch furandere Falle verwendet:

1 *Main> [] — [ ] :: ∀α. [α]2 []

3 *Main> [] :: String

4 ""

5 *Main> 2.3 — 2.3 :: Fractional α ⇒ α6 2.3

I Die Defaulting-Regeln sind im Haskell-Standard41 und im GHCiManual42 beschrieben.

41https://www.haskell.org/onlinereport/haskell2010/haskellch4.html#x10-790004.3.442https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/interactive-evaluation.html#extended-default-rulesStefan Klinger · DBIS Informatik 2 · Sommer 2016 330

Page 331: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Anmerkung: Mehrdeutige Typen · 10.5

I Man kann den ghci mit der Option -Wall starten43, dann wird einDefaulting-Vorgang angezeigt.

1 Prelude> 5

2 <interactive>:3:1: Warning:

3 Defaulting the following constraint(s) to type ‘Integer’

4 (Show a0) arising from a use of ‘print’ at <interactive>:3:1

5 (Num a0) arising from a use of ‘it’ at <interactive>:3:1

6 In a stmt of an interactive GHCi command: print it

7 5

8

9 Prelude> []

10 <interactive>:4:1: Warning:

11 Defaulting the following constraint(s) to type ‘()’

12 (Show t0) arising from a use of ‘print’

13 In a stmt of an interactive GHCi command: print it

14 []

Der Unit-Type () enthalt genau einen Wert, () :: (), ebenfalls Unitgenannt. Er wird oft verwendet wenn man einen Typ braucht der weiterkaum Eigenschaften hat.

43-W legt fest welche Warnungen gezeigt werden sollen. Hier: all = Alle.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 331

Page 332: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Anmerkung: Mehrdeutige Typen · 10.5

Erweiterte Defaulting-Regeln GHCi ab Version 7.8

Die Defaulting-Regeln wurden im Laufe der Zeit erweitert44.

I Aktuelle Versionen des GHCi verwenden oft () als Default.1 GHCi, version 7.8.4: http://www.haskell.org/ghc/ :? for help

2 Prelude> :set -Wall

3 Prelude> toEnum 3

4

5 <interactive>:3:1: Warning:

6 Defaulting the following constraint(s) to type ‘()’

7 ...

8 *** Exception: Prelude.Enum.().toEnum: bad argument

I Hier wird also toEnum 3 :: Enum α ⇒ zu toEnum 3 :: () konkretisiert.I Die Fehlermeldung wird dann von der konkreten Funktion toEnum 3 :: ()

ausgegeben:• () ist zwar Instanz der Enum-Klasse,• enthalt aber nur einen Wert! (Ausprobieren: toEnum 0)

44https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/interactive-evaluation.html#extended-default-rulesStefan Klinger · DBIS Informatik 2 · Sommer 2016 332

Page 333: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Anmerkung: Mehrdeutige Typen · 10.5

~

Obacht

I Defaulting ist eine Krucke die die Arbeit mit dem interaktivenInterpreter vereinfachen soll.

I Dadurch wird die Sprache Haskell nicht klarer, oder einfacher,vielmehr fallen magische Effekte vom Himmel.

I Verlassen Sie sich beim Programmieren nicht auf Defaulting,sondern geben Sie die Typen Ihrer Funktionen an!

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 333

Page 334: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Die Typklasse Show · 10.6

10.6 Die Typklasse Show

I Die Uberfuhrung ihrer Werte in eine externe Reprasentation (vom TypString) ist eine der Kernaufgaben jeder Programmiersprache, z.B. fur• Ein-/Ausgabe von Werten, interaktive Programme,• Speichern/Laden/Ubertragung von Daten.

I In Haskell wird die benotige Funktionalitat von Instanzen derTypklasse Show bereitgestellt45:

1 class Show α where

2 show :: α -> String

3 — Minimal complete definition: show4 ...

45Typklasse Read leistet die Umkehrabbildung, das sog. parsing.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 334

Page 335: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Die Typklasse Show · 10.6

Beispiel Ausgabe von Werten des Typs Frac als Bruche der Formx

y.

1 showFrac :: Frac -> String

2 showFrac (x :/ y) = replicate (div (l-lx) 2) ' ' ++ sx ++ "\n" ++

3 replicate l '-' ++ "\n" ++

4 replicate (div (l-ly) 2) ' ' ++ sy

5 where

6 sx = show x

7 sy = show y

8 lx = length sx

9 ly = length sy

10 l = max lx ly

11

12 instance Show Frac where

13 show = showFrac

Haskell-Interpreter GHCi benutzt show :: Show α ⇒ α→ String, umin interaktiven Sessions Werte darzustellen:

1 *Main> 421 :/ 6546516

2 421

3 -------

4 6546516

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 335

Page 336: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Die Typklasse Show · 10.6

Beispiel “Visualisierung” von Werten des Typs BinTree α .

1 showTree :: Show a => BinTree a -> String

2 showTree = concat . ppTree

3 where

4 ppTree :: Show a => BinTree a -> [String]

5 ppTree Empty = ["@\n"]

6 ppTree (Node l x r) = [show x ++ "\n"]

7 ++ ("|--" ++ ls) : map ("| " ++) lss

8 ++ ("‘--" ++ rs) : map (" " ++) rss

9 where

10 ls:lss = ppTree l

11 rs:rss = ppTree r

12

13 instance Show a => Show (BinTree a) where

14 show = showTree

1 *Main> Node (leaf 1) 2 (Node (leaf 3) 4 Empty)

2 2

3 |--1

4 | |--@

5 | ‘--@

6 ‘--4

7 |--3

8 | |--@

9 | ‘--@

10 ‘--@Stefan Klinger · DBIS Informatik 2 · Sommer 2016 336

Page 337: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Ober-/Unterklassen · 10.7

10.7 Ober-/Unterklassen

In großeren Software-Systemen sind hierarchische Abhangigkeitenzwischen Typklassen ublich (vgl. Vererbung in OO-Sprachen):

Typ T ist Instanz der Typklasse C , was aber nur Sinn macht, wenn Tauch schon Instanz der Typklassen C1, ...,Cn ist.

Beispiel In Haskell stutzt sich Anordnung eines Typs (Ord) auf dieVergleichbarkeit seiner Werte (Eq), cf. Seite 318.

I Jeder Typ in Typklasse Ord muss auch Instanz von Eq sein.I Ist ein Typ in Ord, sind auf seine Werte die Operationen aus Ord und Eq

anwendbar.I Haskell Syntax

class (C1 α, ..., Cn α) => C α where ...

• Die Klassenhierarchie muss azyklisch sein.• Die einzige Typvariable die bei den Ci auftreten darf (und muss), ist α.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 337

Page 338: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Ober-/Unterklassen · 10.7

Anmerkung zur Schreibweise C α => D α

Die Syntax der Type Constraints nicht einfach als Implikation lesen!

1 class C α => D α where

2 ...

C ,D sind also Typklassen.

I Definiert die Klasse D.

I Nur wenn α Instanz von C istdarf α auch zur Instanz von Derklart werden.(

Instanziierungvon α zu D isterlaubt.

)⇒ C α

I Es gilt nicht C α ⇒ D α.

I Es gilt D α ⇒ C α.~

1 instance C α => D (T α) where

2 ...

C ,D Typklassen, T Typkonstruktor.

I Fur alle α die Instanz von Csind wird T α zur Instanz von D.

C α ⇒ D (T α)

I Es ist nicht jeder von Tkonstruierte Typ automatischeine Instanz von D.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 338

Page 339: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Ober-/Unterklassen · 10.7

Haskells numerische Klassen

Beispiel Alle numerischen Typen sind Instanz der Oberklasse Num.

1 class Num α where

2 (+), (-), (*) :: α -> α -> α3 negate :: α -> α4 abs, signum :: α -> α5 fromInteger :: Integer -> α6

7 — Minimal complete definition: All, except negate xor (-)

8 x - y = x + negate y

9 negate x = 0 - x

I Num enthalt nur solche Operationen, die auf alle numerischen Typenanwendbar sind.• +, - und * sind fur alle numerischen Typen sinnvoll.• Jede ganze Zahl lasst sich als reelle, rationale, komplexe, ... Zahl

interpretieren: fromInteger.

I -x ist syntaktischer Zucker fur negate x.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 339

Page 340: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Ober-/Unterklassen · 10.7

Beispiel Speziellere Zahlen: Fractional — Typen mit Division.

1 class Num α => Fractional α where

2 (/) :: α -> α -> α3 recip :: α -> α4 fromRational :: Rational -> α5

6 — Minimal complete definition: fromRational, (recip | (/))7 recip x = 1 / x

8 x / y = x * recip y

I Der Type Constraint Num α druckt aus, dass Teilbarkeit einezusatzliche Eigenschaft von speziellen Numerischen Werten ist.

I Fractional ist eine Spezialisierung von Num (cf. Seite 338)

Fractional α ⇒ Num α

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 340

Page 341: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Ober-/Unterklassen · 10.7

Beispiel Eine andere Teilbarkeit: Integral — ganzzahlige Typen.

1 class (Real α, Enum α) => Integral α where

2 quot :: α -> α -> α3 rem :: α -> α -> α4 div :: α -> α -> α5 mod :: α -> α -> α6 quotRem :: α -> α -> (α, α)7 divMod :: α -> α -> (α, α)8 toInteger :: α -> Integer

9

10 class (Num a, Ord a) => Real a where

11 toRational :: a -> Rational -- "reelle" Zahlen kann man annahern

I Integral ist eine Spezialisierung von Real und Enum:• Ganze Zahlen konnen als Rationale Zahlen aufgefasst,• und auch aufgezahlt werden.

I Die Definition von Klassenhierarchien ist nicht einfach und immer wiederGegenstand von Diskussionen.• Haskells vordefinierte Klassenhierarchie ist in der Sprachdefinition46

beschrieben.

46https://www.haskell.org/onlinereport/haskell2010/haskellch6.html#x13-1270006.3Stefan Klinger · DBIS Informatik 2 · Sommer 2016 341

Page 342: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Ober-/Unterklassen · 10.7

Numerische Konstanten

I Eine numerische Konstante wie 42 ist in Haskell selbst uberladen, dasie – je nach Kontext – als Wert des Typs Integer aber auch z.B. alsDouble angesehen werden kann.

I Die Konstante 42 ist tatsachlich nur syntaktischer Zucker furfromInteger 42.

I Damit gilt 42 :: Num α ⇒ α, also 42 kann jeden beliebigennumerischen Typ annehmen).

1 *Main> :t 42

2 42 :: Num a => a

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 342

Page 343: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

10 · Typklassen und Overloading Ober-/Unterklassen · 10.7

Philip Wadler, and Stephen Blott.How to make Ad-hoc Polymorphism less Ad Hoc.16th Symposium on Principles of Programming Languages. Austin,Texas, 1989.http://www.cs.bell-labs.com/~wadler/papers/class/class.ps.gz

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 343

Page 344: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11Fallstudie: Regulare Ausdrucke

Page 345: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Regular Expressions · 11.1

11.1 Regular Expressions

Mit den bisher eingefuhrten Sprachelementen von Haskell lassen sichbereits substantielle Projekte realisieren. Dieses Kapitel

1. definiert einen algebraischen Datentyp zur Reprasentation von regularenAusdrucken (regular expressions) und

2. entwickelt einen interessanten Algorithmus zum regular expressionmatching, der ohne DFAs operiert.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 345

Page 346: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Regular Expressions · 11.1

Erinnerung

I Regulare Ausdrucke hatten wir bereits besprochen, cf. Seite 31 oder inder Schlusselqualifikation fur Informatiker.

Ihre Struktur kann man leicht angeben (cf. Seite 41), wir nehmen nochErganzungen vor:

RegEx → A — ein Buchstabe aus dem Alphabet

| RegEx , RegEx — verwenden , fur Konkatenation

| RegEx | RegEx — Alternative

| RegEx * — Wiederholung

| ε — Akzeptiert den leeren String

| ∅ — Akzeptiert uberhaupt keinen String

I Symbole konnen Zeichen (Char) sein, aber auch Zahlen, Bits, IP-Pakete,Events einer XML-Parsers, ...Wenn A den Typ der Zeichen reprasentiert, dann steht Strings alsogenerell fur [A].

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 346

Page 347: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Regular Expressions · 11.1

Algebraischer Datentyp RegEx

I Diese Struktur konnen wir offenbar recht einfach in einen algebraischenDatentyp ubersetzen:

1 data RegEx α = RxSym α —A2 | RxSeq (RegEx α) (RegEx α) — r,s

3 | RxAlt (RegEx α) (RegEx α) — r|s

4 | RxRep (RegEx α) — r*

5 | RxEpsilon — ε6 | RxNone —∅7 deriving (Show, Eq)

• Dabei lassen wir das Alphabet (also den Typ der Zeichen) frei.⇒ Typvariable α.

I Die Operatoren + und ? konnen wir bei Bedarf außerhalb desDatentyps definieren als

1 rxPlus r = r ‘RxSeq‘ RxRep r

2 rxOpt = RxAlt RxEpsilon

Frage Was sind die Typen dieser beiden Funktionen?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 347

Page 348: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Regular Expressions · 11.1

Beispiel Den regularen Ausdruck 1, 1?, (0, 0)+ uber dem AlphabetInteger kann man als so konstruieren:

1 *Main> RxSym 1 ‘RxSeq‘ rxOpt (RxSym 1) ‘RxSeq‘ rxPlus (RxSym 0 ‘RxSeq‘ RxSym 0)

2 RxSeq (RxSeq (RxSym 1) (RxAlt RxEpsilon (RxSym 1))) (RxSeq (RxSeq (RxSym 0) (RxSy

3 m 0)) (RxRep (RxSeq (RxSym 0) (RxSym 0))))

Beachte Auf Haskell-Ebene (= Metaebene) klart die expliziteSchachtelung der Konstruktoren (Klammern) mogliche Mehrdeutigkeiten.Ein Konstruktor fur Klammern in RegEx (= Objektebene) ist alsouberflussig. (Diese Idee hatten wir schon einmal, cf. Seite 41.)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 348

Page 349: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke RegEx als Instanz von Show · 11.2

11.2 RegEx als Instanz von Show

I Um Werte des Typs RegEx α ausgeben zu konnen, ist RegEx α Instanzvon Show.

I Um eine moglichst lesbare Ausgabe zu bekommen, programmieren wirdie Ausgabe selbst:

1 instance Show α => Show (RegEx α) where

2 showsPrec _ RxNone = showString "{}"3 showsPrec _ RxEpsilon = showString "eps"

4 showsPrec _ (RxSym c) = shows c

5 showsPrec _ (RxRep r) = showsPrec 2 r . showChar ’*’

6 showsPrec p (RxSeq r s)

7 = showParen (p > 1) (showsPrec 1 r . showString ", " . showsPrec 2 s)

8 showsPrec p (RxAlt r s)

9 = showParen (p > 0) (showsPrec 0 r . showString " | " . showsPrec 1 s)

10

11 *Main> RxSym 1 ‘RxSeq‘ rxOpt (RxSym 1) ‘RxSeq‘ rxPlus (RxSym 0 ‘RxSeq‘ RxSym 0)

12 1, (eps | 1), (0, 0, (0, 0)*)

• Dazu muss man naturlich die deriving Show-Klausel bei der Definition vondata RegEx loschen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 349

Page 350: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke RegEx als Instanz von Show · 11.2

I Einige Dinge sollten klar sein:• Der Constraint Show α erklart sich aus Zeile 4: Wir wollen die Zeichen in

einem regularen Ausdruck ausgeben konnen.• Die Funktion showsPrec behandelt jeden Konstruktor von RegEx a mittels

Pattern Matching.

I Aber: Wieso wird hier showsPrec definiert und nicht show?1○ Warum wird hier Funktionskomposition statt ++ zur Konkatenation von

Strings benutzt?2○ Wozu dient das zusatzliche (meist ignorierte) Argument von showsPrec?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 350

Page 351: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke RegEx als Instanz von Show · 11.2

Zu 1○: Schnelle Konkatenation mit “Fast Strings”

I ++ hat lineare Komplexitat in der Lange des linken Argumentes.

⇒ Wiederholte Konkatenation von Teilergebnissen (Strings) in einerFunktion show, wie sie fur RegEx α notwendig ware, fuhrt zu einer Laufzeit,die quadratisch in der Große des regularen Ausdrucks ist (s. vorn).

Idee Wandle Funktionen der Form

f :: α -> String

um in Funktionen der Form

f ′ :: α -> (String -> String)

Dabei transformiert f ′ x s das Argument x :: α in einen String undkonkateniert das Ergebnis mit s, d.h.

f x ≡ f ′ x ""

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 351

Page 352: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke RegEx als Instanz von Show · 11.2

In der Prelude sind bereits vordefiniert:1 type ShowS = String -> String — “Fast Strings” with constant time concatenation2

3 showString :: String -> ShowS — convert String into a Fast String4 showString = (++)

5

6 showChar :: Char -> ShowS — convert Char into a Fast String7 showChar = (:)

I Das Schlusselwort type fuhrt einen Typ Alias ein. ShowS ist lediglicheine Abkurzung fur String→ String.

I Die Komposition ◦ wirkt auf Fast Strings wie die Konkatenation.

I Durch Anwendung auf den leeren String "" kann ein Fast String in einennormalen String umgewandelt werden.

Beispiel

1 *Main> showString "foo" . showString "bar" . showString "qux" $ ""

2 "foobarqux"

Frage Wieso ist das schneller als einfach ++ zu verwenden?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 352

Page 353: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke RegEx als Instanz von Show · 11.2

Antwort Es geht darum links-tiefe Klammerungen von ++ zu vermeiden.

I a ++ (b ++ c) ist besser als (a ++ b) ++ c.

I ShowS nutzt ++ auch dann rechts-geklammert, wenn ursprunglich linksgeklammert wurde.

Beispiel Konkatenation von "foo", "bar" und "baz":((showString "foo" ◦ showString "bar") ◦ showString "baz"

)""

_ showString((("foo" ++ ) ◦ ("bar" ++ )) ◦ ("baz" ++ )

)""

_ ◦(("foo" ++ ) ◦ ("bar" ++ )) ("baz" ++ "")

_ ◦"foo" ++ ("bar" ++ ("baz" ++ ""))

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 353

Page 354: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke RegEx als Instanz von Show · 11.2

Haskells Typklasse Show ist fur den Einsatz dieser Technik entsprechendvorbereitet:

1 class Show α where

2 show :: α -> String

3 showsPrec :: Int -> α -> ShowS — type ShowS = String -> String

4

5 — Minimal complete definition: show|showsPrec6 show x = showsPrec 0 x ""

7 showsPrec _ x s = show x ++ s

8

.

.

.

9

10 showString :: String -> ShowS

11 showString = (++)

12

13 showChar :: Char -> ShowS

14 showChar = (:)

15

16 shows :: Show α => α -> ShowS

17 shows = showsPrec 0 — mehr dazu gleich...

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 354

Page 355: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke RegEx als Instanz von Show · 11.2

Zu 2○: Einsparen von Klammern bei der Ausgabe

I Setze um einen Konstruktor Klammern genau dann, wenn derumgebende Konstruktor eine hohere Prioritat p aufweist.

Beispiel Wegen der Schachtelung ist die Prioritat des umgebendenKonstruktors immer bekannt. Der außerste Konstruktor liegt in einem“virtuellen Konstruktor” der Prioritat 0 (cf. shows, letzte Folie).

p=0︷ ︸︸ ︷0, 0︸ ︷︷ ︸p=1

| 1, 1︸ ︷︷ ︸p=1

p=2︷ ︸︸ ︷(0, 0︸ ︷︷ ︸p=1

)*

I showsPrec :: Integer→ α→ ShowS

Erstes Argument reprasentiert die Prioritat des umgebendenKonstruktors

I showParen :: Bool→ ShowS→ ShowS

Erstes Argument bestimmt, ob zweites in Klammern gesetzt werden solloder nicht.

Frage Implementation von showParen?Stefan Klinger · DBIS Informatik 2 · Sommer 2016 355

Page 356: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Regulare Sprachen, Wortproblem · 11.3

11.3 Regulare Sprachen, Wortproblem

Jedem regularen Ausdruck r ist die Menge L r der Worte zugeordnet, die rakzeptiert. L r heißt die von r akzeptierte Sprache47.

Definition Das Wortproblem regularer Ausdrucke

Gegeben sei ein regularer Ausdruck r uber einem Alphabet A, sowie eineEingabe i :: [A]. Das Wortproblem ist die Frage, ob i ∈ L r gilt, d.h. obder regulare Ausdruck r die Eingabe i akzeptiert.

I Wir betrachten im Folgenden eine “nicht-Standard”-Losung fur dasWortproblem.

• Die Standard-Losung fur dieses Problem arbeitet mit Hilfe von endlichenAutomaten (Zustandsmaschinen). Die aus r konstruierte Maschine wird dannmit i als Eingabe gestartet; stoppt sie in einem Endzustand, dann ist i ∈ L r .

47Sprachen (also Mengen von Worten) die durch einen regularen Ausdruck beschrieben werdenkonnen, heißen regulare Sprachen, cf. Theoretische Grundlagen der Informatik.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 356

Page 357: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Regulare Sprachen, Wortproblem · 11.3

I Recht einfach konnen wir die akzeptierte Sprache fur jeden Konstruktorangeben:

r L r

∅ ∅ε {[]}c {[c]}s,t { x ++ y | x ∈ L s, y ∈ L t }s|t L s ∪ L ts* {[]} ∪ L (s,s*)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 357

Page 358: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Regulare Sprachen, Wortproblem · 11.3

I Dies konnen wir nutzen, um die Sprachen der nicht-primitivenKonstruktoren zu berechnen.

BeispielL (’x’?) = L(ε|’x’)

= L ε ∪ L ’x’

= {[]} ∪ {[’x’]}= {[], [’x’]}= {"", "x"}

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 358

Page 359: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Regulare Sprachen, Wortproblem · 11.3

Beispiel

L(1+) = L(1, 1*)= { x ++ y | x ∈ L 1, y ∈ L(1*) }= { x ++ y | x ∈ {[1]}, y ∈ L(1*) }= { [1] ++ y | y ∈ L(1*) }= { [1] ++ y | y ∈ {[]} ∪ L(1, 1*) }= { [1] ++ y | y ∈ {[]} ∪ { x ++ z | x ∈ L(1), z ∈ L(1*) }= { [1] } ∪ {[1] ++ y | y ∈ { x ++ z | x ∈ L(1), z ∈ L(1*) }= { [1] } ∪ {[1] ++ y | y ∈ { [1] ++ z | z ∈ L(1*) } }= { [1] } ∪ {[1] ++ [1] ++ y | y ∈ { z | z ∈ L(1*) } }= { [1] } ∪ {[1, 1] ++ y | y ∈ L(1*) }...

= { [1], [1, 1], [1, 1, 1], ...}

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 359

Page 360: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Regulare Sprachen, Wortproblem · 11.3

Schlaue Konstruktoren

I Zwei regulare Ausdrucke r , s sind aquivalent (r ≡ s), falls L r = L s.

I Dies konnen wir nutzen, um bereits bei der KonstruktionVereinfachungen an regularen Ausdrucken vorzunehmen, ohne dieakzeptierte Sprache zu verandern.

Beispiele

I r, ε ≡ ε, r ≡ r

I r | ∅ ≡ ∅ | r ≡ r

I ∅? ≡ εI ∅* ≡ ε

1 rxSeq r RxEpsilon = r

2 rxSeq RxEpsilon r = r

3

4 rxAlt r RxNone = r

5 rxAlt RxNone r = r

6

7 rxOpt RxNone = RxEpsilon

8

9 rxRep RxNone = RxEpsilon

I Diese wrapper-Funktionen werden auch smart constructors genannt,weil sie prinzipiell weitergehende Bedingungen fur die Datenstrukturerzwingen48 konnen.

48Module wie z.B. Data.Set exportieren die “echten” Konstruktoren fur Set α nicht!Stefan Klinger · DBIS Informatik 2 · Sommer 2016 360

Page 361: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Regulare Sprachen, Wortproblem · 11.3

Frage Wie lauten die Vereinfachungen hier?

I ∅, r ≡I r, ∅ ≡I ∅+ ≡I ε+ ≡I r** ≡I r*? ≡

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 361

Page 362: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Die Ableitung regularer Ausdrucke · 11.4

11.4 Die Ableitung regularer AusdruckeI Das Wortproblem: Wir suchen eine Funktion, die den Input i gegen den

regularen Ausdruck r matcht:

1 match :: RegEx α -> [α] -> Bool

2 match r i = i ∈ L r — Pseudo-Code!

• Da L r potenziell unendlich ist,scheidet explizites Aufzahlenaus.

Idee Wir zerlegen das Problem: Die Eingabe i hat die Form c :cs.

1. Konnen Worte in L r uberhaupt mit c anfangen?(Wenn nicht, sind wir fertig: i 6∈ L r ⇒ match r i _ False)

2. Wenn ja, welcher regulare Ausdruck r ′ beschreibt die erlaubten Restealler Worte in L r die mit c anfangen?

3. Gilt cs ∈ L r ′? —Dieses Problem ist einfacher!

Notation r ′ nennen wir die Ableitung von r nach c , und schreiben:

r ′ = ∂c r

Also muss gelten: L(∂c r) = { cs | c:cs ∈ L r }.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 362

Page 363: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Die Ableitung regularer Ausdrucke · 11.4

Was bleibt zu tun?

I Wenn wir ∂c r fur jedes Symbol c und jeden regularen Ausdruck rberechnen konnen, ist das Wortproblem weitgehend gelost. Denn z.B.

[c1, c2, c3] ∈ L r⇔

[c2, c3] ∈ L(∂c1r

)⇔

[c3] ∈ L(∂c2(∂c1r)

)⇔

[ ] ∈ L(∂c3(∂c2(∂c1r))

)I Damit haben wir unser Problem gelost, sofern wir nun noch entscheiden

konnen, ob ein regularer Ausdruck die leere Eingabe [] akzeptiert.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 363

Page 364: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Die Ableitung regularer Ausdrucke · 11.4

I Diesen sogenannten nullable Test kann man tatsachlich sehr einfachausfuhren:

1 nullable :: RegEx α -> Bool

2

3 nullable RxNone = False — akzeptiert keine Eingabe, auch nicht die leere4 nullable RxEpsilon = True — akzeptiert genau die leere Eingabe5 nullable (RxSym _) = False — hier muss genau ein Buchstabe stehen6

7 nullable (RxRep r) = ?

8 nullable (RxSeq r s) = ?

9 nullable (RxAlt r s) = ?

Frage Wie lauten die fehlenden Gleichungen?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 364

Page 365: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Die Ableitung regularer Ausdrucke · 11.4

I Seiderive :: Eq α ⇒ RegEx α→ α→ RegEx α

die Haskell-Implementation von ∂, also ∂x r = derive r x .

I Dann ist match ein Einzeiler:

1 match :: Eq α => RegEx α -> [α] -> Bool

2 match r = nullable . foldl derive r

Fragen Warum fold-left? Wofur wird Eq α benotigt?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 365

Page 366: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Die Ableitung regularer Ausdrucke · 11.4

Beispiel

foldl derive r [c0, c1, c2]_foldl foldl derive (r ‘derive‘ c0) [c1, c2]_foldl foldl derive ((r ‘derive‘ c0) ‘derive‘ c1) [c2]_foldl foldl derive (((r ‘derive‘ c0) ‘derive‘ c1) ‘derive‘ c2) []_foldl ((r ‘derive‘ c0) ‘derive‘ c1) ‘derive‘ c2

Frage Verhalt sich match r [] richtig, d.h. wird auch die leere Eingabekorrekt gematcht?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 366

Page 367: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Die Ableitung regularer Ausdrucke · 11.4

Die Ableitungsfunktion ∂

I Es verbleibt die Implementation von derive:

1 derive :: Eq α => RegEx α -> α -> RegEx α2

3 derive (RxSym c) x

4 | c == x — Hier brauchen wir Eq α5 = rxEpsilon

6

7 derive r@(RxRep s) x

8 = derive s x ‘rxSeq‘ r

9

10 derive (RxAlt r s) x

11 = derive r x ‘rxAlt‘ derive s x

12

13 derive (RxSeq r s) x — Dies ist der einzige trickreiche Schritt~

14 | nullable r

15 = (derive r x ‘rxSeq‘ s) ‘rxAlt‘ derive s x

16 | otherwise

17 = derive r x ‘rxSeq‘ s

18

19 derive _ _ — Alle anderen Falle: ε, ∅, RxSym c | c 6=x .20 = rxNone

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 367

Page 368: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Die Ableitung regularer Ausdrucke · 11.4

Beispiel Die Ableitung derive implementiert tatsachlich unsere Idee (cf.Seite 362, unten)

L (∂xε)={ cs | x:cs ∈ L ε }

={ cs | x:cs ∈ {[]} }

=∅

=L ∅

L (∂xx)={ cs | x:cs ∈ L x }

={ cs | x:cs ∈ {[x]} }

={[]}

=L ε

L (∂x(r|s))={ cs | x:cs ∈ L (r|s) }

={ cs | x:cs ∈ L r ∪ L s }

={ cs | x:cs ∈ L r } ∪ { cs | x:cs ∈ L s }

=L (∂x r) ∪ L (∂xs)

=L (∂x r|∂xs)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 368

Page 369: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

11 · Fallstudie: Regulare Ausdrucke Die Ableitung regularer Ausdrucke · 11.4

1 *Main> r

2 1, (eps | 1), (0, 0, (0, 0)*)

3

4 *Main> derive it 1 — im GHCi ist it das Ergebnis der letzten Berechnung5 (eps | 1), (0, 0, (0, 0)*)

6 *Main> derive it 0

7 0, (0, 0)*

8 *Main> derive it 0

9 (0, 0)*

10 *Main> derive it 1

11 {}12

13 *Main> foldl derive r [1,0]

14 0, (0, 0)*

15 *Main> nullable it

16 False

17

18 *Main> foldl derive r [1,0,0]

19 (0, 0)*

20 *Main> nullable it

21 True

22

23 *Main> match r [0,1,0,1,0]

24 False

25 *Main> match r [1,1,0,0,0,0]

26 True

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 369

Page 370: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12Lazy Evaluation

Page 371: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation

I Im λ-Kalkul ist die Reihenfolge der Reduktionsschritte (_) fur einenAusdruck nicht a priori festgelegt.

I Bisher haben wir nur intuitiv erklart, wie lazy evaluation arbeitet:Teilausdrucke werden erst bei Bedarf reduziert.

I Im Folgenden werden wir genauer betrachten• was das bedeutet (→ nicht-strikte Semantik),• und wie das implementiert werden kann (→ Auswertestrategien).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 371

Page 372: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Strikte und nicht-strikte Semantik · 12.1

12.1 Strikte und nicht-strikte Semantik

I Strikte Programmiersprachen beginnen die Auswertung eines Ausdrucksbei der innersten Anwendung.

f (g x) —zuerst wird g x reduziert

I Nicht-strikte Sprachen fangen dagegen mit der außersten Anwendungan.

f (g x) —zuerst wird f (...) reduziert

~

Wichtig Hier liegt ein semantischer Unterschied vor, d.h., strikteund nicht-strikte Semantik ordnen dem gleichen Term unter Umstandenverschiedene Bedeutungen zu.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 372

Page 373: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Strikte und nicht-strikte Semantik · 12.1

Beispiel Sei g x = ⊥ eine nicht terminierende (oder undefinierte)Berechnung, und sei f = λy . 3.

Der Term f (g x) hat unter...

... strikter Semantik den Wert ⊥, weil vor der Reduktion von f (...) dasArgument (endlos) reduziert wird.

... nicht-strikter Semantik den Wert 3, weil zuerst die Anwendung von freduziert wird: f (g x) = (λy . 3) (g x) _

β3

Beispiele

I Haskell hat nicht-strikte Semantik.

1 Prelude> take 10 [1..]

2 [1,2,3,4,5,6,7,8,9,10]

• Ebenso Miranda (ein direkter Haskell-Vorganger) und Clean.

I Die meisten Programmiersprachen sind jedoch strikt, z.B., C, Java, ML(eine funktionale Sprache die starken Einfluss auf Haskell hatte).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 373

Page 374: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Strikte und nicht-strikte Semantik · 12.1

Definition Strikte Funktion

Eine Funktion f heisst strikt, genau dann wenn

x _ ⊥ ⇒ f x _ ⊥andernfalls heisst die Funktion nicht-strikt.

I In einer strikten Programmiersprache sind alle Funktionen strikt.• Im Gegensatz zu nicht-strikten Sprachen lasst sich das Konstruktif · then · else · fi nicht als Funktion :: Bool→ α→ α→ α ausdrucken.

I In einer nicht-strikten Sprache darf eine Funktion auch dann einen Wertzuruckgeben, wenn ihr Argument ⊥ ist.

1 Prelude> const 3 $ length [1..]

2 3

1 Prelude> const 3 undefined —⊥2 3

Das muss allerdings nicht fur jede Funktion gelten, (1 +) ist z.B. strikt:

1 Prelude> 1 + length [1..]

2 — terminiert nicht1 Prelude> 1 + undefined

2 *** Exception: Prelude.undefined

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 374

Page 375: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Auswertestrategien · 12.2

12.2 Auswertestrategien

I Zwei mogliche Reduktionsstrategien sind

1. Applicative Order Reduction(aka. Eager Evaluation oder Call by Value) und

2. Normal Order Reduction (+ Sharing)(aka. Lazy Evaluation).

I Sie legen dabei jeweils fest, welcher von im Allgemeinen mehrerenreduzierbaren Teilausdrucken (Redex, reducible expression) in einemAusdruck als nachster reduziert wird.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 375

Page 376: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Auswertestrategien · 12.2

Beispiel Fur die Auswertung des Ausdrucks const (sqr 4) (sqr 2) seienconst und sqr definiert durch:

const x y = xsqr z = × z z

Applicative Order Reduction wahltjeweils den linkesten innerstenRedex zur Reduktion aus:

const (sqr 4) (sqr 2)_β const (× 4 4) (sqr 2)_δ const 16 (sqr 2)_β const 16 (× 2 2)_δ const 16 4_β 16

Normal Order Reduction wahltjeweils den außersten Redex zurReduktion aus:

const (sqr 4) (sqr 2)_β sqr 4_β × 4 4_δ 16

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 376

Page 377: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Auswertestrategien · 12.2

In der Baumnotation fur Ausdrucke, in der die Applikation f e1 e2 durch

@

@

f e1

e2

reprasentiert wird, reduziert Applicative Order Reduction zuerst dieinneren Teilbaume e1 und e2 wahrend Normal Order Reduction zuvor denaußeren linken Pfad von der Wurzel zu f reduziert (aka. Spine).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 377

Page 378: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Auswertestrategien · 12.2

Beispiel Reduktion von const (sqr 4) (sqr 2) in Applicative Order.

@

@

const @

sqr 4

@

sqr 2

sqr=

@

@

const @

λz

@

@

× z

z

4

@

sqr 2

@

@

const @

@

× 4

4

@

sqr 2

nachste Folie

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 378

Page 379: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Auswertestrategien · 12.2

@

@

const 16

@

sqr 2

const=

@

@

λx

λy

x

16

@

sqr 2

@

λy

16

@

sqr 2

sqr_β

@

λy

16

@

@

× 2

2

@

λy

16

4 _β

16

Faustregel Bei Reduktion in Applicative Order wird der nachste Redexdurch den linkesten innersten reduziblen Knoten bestimmt. (Literatur:leftmost innermost).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 379

Page 380: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Auswertestrategien · 12.2

Beispiel Betrachten im Gegensatz dazu die Reduktion vonconst (sqr 4) (sqr 2) in Normal Order.

@

@

const @

sqr 4

@

sqr 2

const=

@

@

λx

λy

x

@

sqr 4

@

sqr 2

@

λy

@

sqr 4

@

sqr 2

@

sqr 4sqr_β

@

@

× 4

4 _δ

16

Faustregel In Normal Order wird als nachstes der Knoten links außenim Baum reduziert. (Literatur: leftmost outermost)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 380

Page 381: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Graph-Reduktion · 12.3

12.3 Graph-Reduktion

Es ist nicht wahr, dass Normal Order Reduction – in der Form wie ebenbesprochen – immer weniger Reduktionen benotigt als Applicative OrderReduction.

Beispiel Fur den Ausdruck sqr (+ 4 2)...

...benotigt Normal OrderReduction vier Reduktionen, ...

sqr (+ 4 2)_β × (+ 4 2) (+ 4 2)_δ × 6 (+ 4 2)_δ × 6 6_δ × 36

...Applicative Order Reductionkommt mit drei Reduktionen aus.

sqr (+ 4 2)_δ sqr 6_β × 6 6_δ 36

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 381

Page 382: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Graph-Reduktion · 12.3

Term-Graphen

I Das Problem besteht hier in der Duplizierung eines Teilausdrucks, sodass dieser Teilausdruck zweimal reduziert werden muss.

I Jede Definition, in der ein Parameter auf der rechten Seite mehr alseinmal auftritt, leidet unter diesem Problem (sqr = λz . × z z).

I FPLs arbeiten daher intern mit Term-Graphen, nicht mit Baumen, sokonnen gemeinsame Teilausdrucke einfach reprasentiert werden (sharing).

(Eine Compilertechnik dazu ist die Common Subtree Elimination, welche identischeTeilausdrucke zusammenfasst.)

I Die Auswertung erfolgt dann durch Graph-Reduktion.

I Genau auf diese Weise sind auch let...in und where effizient realisierbar.

I Beachte: Korrektheit der Graph-Reduktion beruht entscheidend auf derSeiteneffektfreiheit!

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 382

Page 383: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Graph-Reduktion · 12.3

Beispiel Mit Sharing benotigt auch Normal Order Reduction vonsqr (+ 4 2) lediglich drei Reduktionen:

@

sqr @

@

+ 4

2

@

@

× @

@

+ 4

2

@

@

× 6

36

Wichtig Mit Graph-Reduktion benotigt Normal Order Reduction niemehr Reduktionsschritte als Applicative Order Reduction.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 383

Page 384: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Terminierung · 12.4

12.4 TerminierungApplicative Order Reduction findet mitunter keine Normalform, weil dieReduktionsfolge nicht terminiert.

Beispiel Zusatzlich zu fst seien noch answer und loop definiert:

answer = fst (42, loop)

loop = tail loop

I Die Auswertung von answer mittels Applicative Order Reductionterminiert nicht:

answer _ fst (42, loop) (answer)_ fst (42, tail loop) (loop)_ fst (42, tail (tail loop)) (loop)_ fst (42, tail (tail (tail loop))) (loop)_ ...

I Normal Order Reduction reduziert dagegen wie folgt:

answer _ fst (42, loop) (answer)_ 42 (fst)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 384

Page 385: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Terminierung · 12.4

Eigenschaften

Satz

Terminieren sowohl Applicative Order als auch Normal Order Reduction,so liefern beide dasselbe Ergebnis.

Satz

Wenn ein Ausdruck uberhaupt eine Normalform besitzt, dann kann siedurch Normal Order Reduction gefunden werden.Ein Teilausdruck wird nur dann reduziert, wenn dies zur Berechnung desErgebnisses wirklich notwendig ist.

Beide Satze ohne Beweis

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 385

Page 386: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Weak Head Normal Form (WHNF) · 12.5

12.5 Weak Head Normal Form (WHNF)

I Zentrales Ziel der Lazy Evaluation ist es, alle unnotigen Reduktionen zuvermeiden.

I Nicht-strikte FPLs reduzieren Ausdrucke daher nicht auf ihre tatsachlicheNormalform, sondern lediglich auf die sog. weak head normal form(WHNF).

I WHNF definiert ein Stop-Kriterium fur Normal Order Reduction.

Beispiel Der Ausdruck x : xs ist auch dann schon in WHNF, wenn x undxs jeweils noch nicht reduziert wurden.Gleichwertig: Der Baum

@

@

: x

xs

ist in WHNF, weil kein top-level Redex mehr existiert (obwohl nochinnere Redexe existieren).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 386

Page 387: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Weak Head Normal Form (WHNF) · 12.5

Definition Weak Head Normal Form (WHNF) Vorlaufig, cf. Seite 397

Ein Ausdruck f e1 e2 ... en ist genau dann in Weak Head Normal Form,wenn gilt

∀m, m ≤ n. f e1 ... em ist kein Redex.

Gemaß dieser Definition ist der Baum rechtsgenau dann in WHNF, wenn er keinentop-level Redex besitzt, d.h., wenn keinerder mit f beginnenden Ausdrucke

f e1

f e1 e2

f e1 e2 e3

f e1 e2 e3 e4

auf dem linken außeren Zweig des Baumesreduzierbar ist.

@

@

@

@

f e1

e2

e3

e4

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 387

Page 388: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Weak Head Normal Form (WHNF) · 12.5

I Die Reduktion stoppt, sobald kein top-level Redex mehr existiert.Dadurch wird die evtl. unnotige Auswertung innerer Redexe verhindert.

I Ein weiterer Vorteil: Wenn ein top-level Redex keine freien Variablenbeinhaltet (und damit auch seine Argumente nicht), benotigt dieReduktionsmaschinerie keine α-Konversion, cf. Seite 103.

Beispiele fur Terme in WHNF:

42 — Konstanten, dabei ist n = 0.+ 3 — Partiell angewandte primitive Funktion.λx . + 2 3 — Nicht angewandte Funktionen (auch hier n = 0).(sqr 2, sqr 3) — Tupelkonstruktor, nicht weiter reduzierbar.[+ 2 3, length [1..]] — cons, nicht weiter reduzierbar.

I Die letzten drei Ausdrucke sind in WHNF, aber nicht in Normalform(dazu mussten die inneren Redexe noch reduziert werden). Ihrtop-level-Ausdruck ist jedoch irreduzibel.

I Der letzte Ausdruck hat gar keine Normalform.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 388

Page 389: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Weak Head Normal Form (WHNF) · 12.5

Beispiele fur Lazy WHNF Reduction

Lazy Evaluation erlaubt einen daten-orientierten Programmierstil (auch“listful style”), der in einer Sprache mit Applicative Order Reduction hochstineffizient ware:

I Daten-orientierte Programme konstruieren (komplexe, unendliche)Datenstrukturen und

I manipulieren diese Datenstrukturen Schritt fur Schritt durch Anwendungeiner Komposition relativ simpler Funktionen.

Dank Lazy Evaluation werden die Datenstrukturen nie komplett erzeugt.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 389

Page 390: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Weak Head Normal Form (WHNF) · 12.5

Beispiel Berechne die Summe der Quadrate der Zahlen von 1...n

I “Klassische” rekursive Losung:

1 sumsqr :: Integer -> Integer

2 sumsqr 1 = 1

3 sumsqr n = n^2 + sumsqr (n-1)

I Die Daten-orientierte Losung 1○ konstruiert die Liste [1..n], 2○berechnet die Quadrate der Listenelemente [1,4,...n2] und 3○ summiertdie Elemente dieser Liste:

sumsqr’ n = sum︸︷︷︸3○

. map (ˆ2)︸ ︷︷ ︸2○

$ [1..n]︸ ︷︷ ︸1○

• sumsqr’ scheint mit dem Heap verschwenderisch umzugehen, denn dieSchritte 1○ und 2○ bauen potentiell große Listen als Zwischenergebnisse auf.

• Tatsachlich erzeugt Lazy Evaluation + WHNF wahrend der Reduktionkeine der beiden Listen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 390

Page 391: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Weak Head Normal Form (WHNF) · 12.5

Beispiel Reduktion von sumsqr’ 3

sumsqr′ 3_

sum ◦map (ˆ 2) $ [1..3]_

sum (map (ˆ 2) [1..3]))_

sum (map (ˆ 2) (1 : [2..3]))_

sum ((ˆ 2) 1 : map (ˆ 2) [2..3])_

(ˆ 2) 1 + sum (map (ˆ 2) [2..3])_

1 + sum (map (ˆ 2) [2..3])_

1 + sum ((ˆ 2) 2 : map (ˆ 2) [3..3])_

1 + (ˆ 2) 2 + sum (map (ˆ 2) [3..3])_

1 + 4 + sum (map (ˆ 2) [3..3])_

5 + sum (map (ˆ 2) [3..3])_

5 + sum ((ˆ 2) 3 : map (ˆ 2) [ ])_

5 + (ˆ 2) 3 + sum (map (ˆ 2) [ ])_

5 + 9 + sum (map (ˆ 2) [ ])_

14 + sum (map (ˆ 2) [ ])_

14 + sum [ ] _ 14 + 0 _ 14

I Das jeweils erste Listenelementwird sofort quadriert und imnachsten Schritt Teil derGesamtsumme.

I Beachte: Hier steht [1..3] nichtfur die konstante Liste [1,2,3],sondern fur den Listengenerator,der die Liste der Elemente 1 bis 3

bei Bedarf erzeugen kann.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 391

Page 392: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Weak Head Normal Form (WHNF) · 12.5

“Effizienzsteigerung” durch listful style

I Der listful style of programming ermoglicht also die effiziente Verkettungeines Generators mit einer Sequenz (Komposition) von Transformern.

I Da Lazy Evaluation den Generator nur bei Bedarf nach einemnachsten Listenelement aufruft (data on demand), kann der Generatorprinzipiell auch eine unendliche Datenstruktur erzeugen. Darauf kommenwir gleich zuruck.

I Ausdrucksauswertung mittels Lazy Evaluation zeigt oft nicht sofortoffensichtliche Effekte bzgl. der Effizienz...(Laufzeitanalyse ist tatsachlich schwierig)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 392

Page 393: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Weak Head Normal Form (WHNF) · 12.5

Effizient oder nicht?

Beispiel Bestimme das Minimum aus einer Liste von Zahlen“Listful” Losung: 1○ Sortiere die Liste (mittels Insertion Sort, isortsiehe unten), 2○ dann enthalt der Kopf der Liste das Minimum:

min = head . isort (<)

Insertion Sort sortiert eine Liste, indem das jeweilige Kopfelement derunsortieren Liste an seine korrekte Position (bzgl. lt) mittels ins in dieErgebnisliste einfugt wird:

1 isort :: (α -> α -> Bool) -> [α] -> [α]2 isort lt [] = []

3 isort lt (x:xs) = ins x (isort lt xs)

4 where

5 ins x [] = [x]

6 ins x (x’:xs) | x ‘lt‘ x’ = x:x’:xs

7 | otherwise = x’:ins x xs

Frage Wie effizient ist Insertion Sort?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 393

Page 394: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Weak Head Normal Form (WHNF) · 12.5

Reduktion mittels Lazy Evaluation zeigt, dass die Argumentliste nievollstandig sortiert wird: min hat lineare Komplexitat trotz Ausnutzungvon isort in O(n2):

min [8, 6, 1, 7, 5]_

(head . isort (<)) [8, 6, 1, 7, 5]_

head (isort (<) [8, 6, 1, 7, 5])_

head (ins 8 (ins 6 (ins 1 (ins 7 (ins 5 [])))))_

head (ins 8 (ins 6 (ins 1 (ins 7 [5]))))_

head (ins 8 (ins 6 (ins 1 (5 : ins 7 []))))_

head (ins 8 (ins 6 (1 : (5 : ins 7 []))))_

head (ins 8 (1 : (ins 6 (5 : ins 7 []))))_

head (1 : ins 8 (ins 6 (5 : ins 7 [])))_

1

I In allen Fallen benotigt ins nurje einen Reduktionsschritt, umdie Liste, in die eingefugt wird,in WHNF zu bringen.

I Der gesamte Listenrest wird niesortiert und am Ende ohnehin“weggeworfen”, da head

lediglich auf den Listenkopfzugreift.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 394

Page 395: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Unendliche Listen · 12.6

12.6 Unendliche Listen

I Die Eigenschaft, Ausdrucke jeweils nur in ihre WHNF zu uberfuhren,verleiht lazy FPLs die Fahigkeit auch auf (potenziell!) unendlichenDatenobjekten, vor allem Listen, zu operieren.

I Im Zusammenspiel mit dem listful style of programming ergibt sich einsehr eleganter und doch effizienter Programmierstil.

I~

Es ist wichtig, sich klarzumachen, dass unendliche Listen nicht dieEigenschaften unendlicher mathematischer Objekte, etwa Mengen,besitzen.49

49Eigentlich sind sie keine unendlichen Listen, sondern Generatoren, die unbeschrankt viele Elemente

erzeugen konnten.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 395

Page 396: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Unendliche Listen · 12.6

Beispiel Wahrend die Set Comprehension

{x2 | x ∈ {1, 2, 3, ...}, x2 < 10}

das endliche Objekt {1, 4, 9} bezeichnet, liefert die (eben nicht aquivalente)List Comprehension

[ x2 | x ← [1..], x2 < 10 ]

Interpreter [1,4,9 —und terminiert nicht (tatsachlich sehen wir1:4:9:⊥). Korrekt ware hier etwa

(takeWhile (<10) . map (^2)) [1..]

Frage Sei cubes = [ x3 | x ← [1..] ].Was ist der Wert von elem 64 cubes? Und von elem 65 cubes?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 396

Page 397: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Unendliche Listen · 12.6

WHNF und strikte Funktionen

Wir brauchen noch eine Erweiterung der Definition von WHNF:

I Strikte Funktionen mit genugend Argumenten erzwingen dieReduktion ihrer Argumente auf WHNF. Demnach ist

+ (× 2 3) (− 7 2) noch nicht in WHNF,

obwohl der top-level Ausdruck + e1 e2 nicht reduzibel ist.

• Da der strikte Operator + mit genugend Argumenten versorgt wird, werdenzunachst e1 _ 6 und e2 _ 5 auf WHNF reduziert, und dann + 6 5 _ 11.

I Sind nicht genugend Argumente vorhanden, so werden auch dievorhandenen nicht reduziert. Demnach ist

+ (× 2 3) bereits in WHNF,

obwohl + strikt ist, und × 2 3 noch reduziert werden konnte.• Das wird klar wenn man Sections (cf. Seite 139) als syntaktischen Zucker

auffasst: Der Ausdruck + (× 2 3) = λx .+ (× 2 3) x ist offenbar einenicht-angewandte λ-Abstraktion (Argument fehlt), und deshalb in WHNF.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 397

Page 398: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Unendliche Listen · 12.6

iterate

Die Funktion iterate aus der standard prelude ist ein Generatorunendlicher Listen (cf. Seite 80 zur iterativen Wurzelbestimmung):

iterate f x = x : iterate f (f x)

Informell berechnet iterate f x also [x,f x,f 2 x,f 3 x,...]

Beispiel

iterate (+1) 1 = [1, 2, 3, 4, 5,...]iterate (*2) 1 = [1, 2, 4, 8, 16,...]

iterate (‘div‘ 10) 2718 = [2718, 271, 27, 2, 0, 0, 0,...]

oder auch

[m..n] ≡ takeWhile (<= n) (iterate (+1) m)

→ Fur den listful style ist iterate ein idealer Generator.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 398

Page 399: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

12 · Lazy Evaluation Unendliche Listen · 12.6

Beispiel digits bestimmt die Liste der Ziffern einer ganzen Zahl

digits = reverse . map (‘mod‘ 10) . takeWhile (/= 0) . iterate (‘div‘ 10)

Diese Sequenz aus Generator und Transformern berechnet dann digits2718 wie folgt:

2718

↓ iterate (‘div‘ 10)

[2718, 271, 27, 2, 0, 0, 0,...]↓ takeWhile (/= 0)

[2718, 271, 27, 2]

↓ map (‘mod‘ 10)

[8, 1, 7, 2]

↓ reverse

[2, 7, 1, 8]

Frage: Was berechnet die folgende ganz analog definierte Funktion foo?

foo n = map (take n) . takeWhile (/= []) . iterate (drop n)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 399

Page 400: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13Typinferenz

Page 401: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Typsysteme · 13.1

13.1 Typsysteme

I Ziel der Typprufung: alle Operanden von Operatoren haben einenkompatiblen Typ.• ... “Operatoren” sehr allgemein verstanden (z.B. auch Zuweisungen,

Funktionsaufrufe, ...)

I Kompatibler Typ: Vom Operator erwarteter Typ.• Manche Sprachen erlauben auch Typen, deren Werte automatisch in den

erwarteten Typ konvertiert werden konnen.• Diese automatische Typkonvertierung nennt man Coercion, die zugehorigen

Regeln sind oft komplex50.

I Ein Typfehler besteht dann in der Anwendung eines Operators auf einenWert inkompatiblen Typs.

50https://www.destroyallsoftware.com/talks/watStefan Klinger · DBIS Informatik 2 · Sommer 2016 401

Page 402: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Typsysteme · 13.1

Geschmacksrichtungen tatsachlich ist diese Einteilung etwas schwammig

static/dynamic typing Ein statisches Typsystem uberpruft dieTypkorrektheit beim Kompilieren (Haskell, Java, C).• Zur Laufzeit liegen evtl. gar keine Typinformationen mehr vor (C).• Ein dynamisches Typsystem pruft erst zur Laufzeit (Python).

strong/weak typing Ein starkes Typsystem erkennt alle Typfehler,ggf. aber erst zur Laufzeit.• Ein schwaches Typsystem kann bei unpassenden Typen zu unerwartetem

Verhalten fuhren (C), oder das Programm abbrechen.

polymorphic typing Polymorphie erlaubt die Verwendung einer Funktionmit verschiedenen aber passenden Typen.• Parametrische Polymorphie — Funktionen werden ohne Annahme uber den

Typ des Argumentes implementiert.• Ad-hoc Polymorphie — Fur den jeweiligen Typ wird die passende

Implementierung einer Funktion ausgewahlt.• Subtyping — Funktionen fur einen bestimmten Typ (z.B. Mammal) konnen

auch Werte von Untertypen (z.B. Bunny) verarbeiten.

Insgesamt sind Bezeichnungen wie statisch/dynamisch oder stark/schwach eher alsextreme Pole eines Spektrums von moglichen Auspragungen zu verstehen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 402

Page 403: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Typsysteme · 13.1

Programmierer profitieren von der Typprufung ihrer Programme:

I “Well-typed programs do not ‘go wrong’.” (Robin Milner): eintypkorrektes Programm wendet Funktionen nur auf Werte an, fur die sieauch definiert wurden.

I Viele ansonsten schwer zu entdeckende Fehler werden durch denType-Checker zur Compile-Zeit erkannt.

1 Prelude> foldl sqrt

2

3 <interactive>:2:7:

4 Occurs check: cannot construct the infinite type: b ~ a -> b

Aber auch der Compiler und die Laufzeitumgebung ziehen Vorteile ausder Typisierung:

I Fur ein typkorrektes Programm muss das Laufzeitsystem der Sprachekeine Tests auf die Typkorrektheit ausfuhren (⇒ kurzere Laufzeiten).

I Der Compiler muss entsprechend keinen Code fur solche Tests generieren(⇒ kompakterer Objekt-Code).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 403

Page 404: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Typsysteme · 13.1

Uberprufung der Typkorrektheit

I Type Checking• Programmierer deklariert zu jedem Objekt (Variablen, Parameter, ...) den

gewunschten Typ.• Compiler (statisch) bzw. Laufzeitsystem (dynamisch) pruft Typregeln und

meldet ggf. Typfehler.

I Type Inference• Programmierer gibt (fast) keine explizite Typisierung von Objekten an.• Compiler leitet gewunschten Operandentyp aus Operatoren und

Inferenzregeln ab, meldet ggf. Typfehler.

Die meisten Programmiersprachen verwenden teilweise Typinferenz (z.B.bei numerischen Konstanten), fordern aber auch Typdeklarationen, diedann (statisch/dynamisch) gepruft werden.

Haskell basiert (fast ausschließlich) auf Typinferenz.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 404

Page 405: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Automatische Typinferenz · 13.2

13.2 Automatische Typinferenz

I In Haskell ist es bis auf wenige Ausnahmefalle nicht notwendig (abersehr hilfreich), Werte und Ausdrucke mit ihren jeweiligen Typen zuannotieren. Stattdessen leitet der Compiler die Typisierungautomatisch ab.

I Die Typinferenz-Komponente eines Compilers

1. pruft, ob ein Programm nach den Typregeln der Sprache korrekt typisiert ist(type check), und

2. (sollte 1○ erfullt sein) leitet automatisch den Typ jedes Ausdrucks innerhalbdieses Programms ab (type inference).

I Diese beiden Aufgaben werden verschrankt (nicht eine nach der anderen)ausgefuhrt.

I Mittels Intuition und “scharfem Hinsehen” lassen sich die Punkte 1○ und2○ fur viele Ausdrucke und Funktionsdefinitionen auch intuitiv ableiten.

Der spater vorgestellte Inferenzalgorithmus orientiert sich an dieserIntuition.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 405

Page 406: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Automatische Typinferenz · 13.2

Beispiel Typinferenz fur die Funktion foldr mit folgender Definition:

foldr f z = go where go [ ] = zgo (x : xs) = f x (go xs)

“Scharfes Hinsehen” liefert:

1. go operiert offensichtlich auf Listen und hat daher den Typ [α]→ β.

2. Sowohl z als auch f x (go xs) konnen ein Ergebnis von go darstellen, undhaben also den Typ β.

3. Da x :: α und (go xs) :: β, muss f vom Typ α -> β -> β sein.

Also:foldr :: (α→ β → β)→ β → [α]→ β

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 406

Page 407: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Automatische Typinferenz · 13.2

Beobachtungen

Diese intuitive Typinferenz umfasst dabei die

1. Bestimmung eines Typs fur einen Ausdruck an sich, wie etwa im letztenBeispiel fur go. Im Allgemeinen wird dieser Typausdruck Typvariablenbeinhalten.

2. Bestimmung eines Typs fur einen Teilausdruck bereits typisierterAusdrucke, wie eben fur z und f geschehen.

Typkorrekt Soll der Gesamtausdruck typkorrekt sein, durfen sich diedabei abgeleiteten Typen nicht widersprechen, d.h. sie mussen durchgeeignete Substitution von Typvariablen in dieselbe Form gebracht werdenkonnen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 407

Page 408: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Automatische Typinferenz · 13.2

Kernsprache fur Typinferenz

Um den Rahmen der Betrachtungen nicht zu sprengen, besprechen wir hiereinen Typinferenz-Algorithmus fur einen erweiterten λ-Kalkul:

I Wir erweitern den einfachen λ-Kalkul um Konstanten (cf. Seite 94) undlokale Definitionen via let ... in , und erhalten

Expr → Const Konstanten| Var Variablen| Expr Expr Applikation| λVar. Expr λ-Abstraktion| let Var = Expr in Expr lokale Definition

• Der let-Ausdruck kann hier tatsachlich nur eine Variable binden, erlaubtuns aber immerhin Rekursion einzufuhren.

• Ublicherweise wird ein machtigeres let verwendet, das z.B. auch wechselseitigrekursive Definitionen zulasst.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 408

Page 409: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Inferenzregeln · 13.3

13.3 Inferenzregeln

I Inferenzregeln werden in der Logik oft in der Form

Pramisse1 Pramisse2 Pramisse3verwendete Regel

Folgerung

notiert.

• Auf dieser Notation bauen z.B. Systeme naturlichen Schließens auf, eineFamilie von Kalkuli aus der Logik.

I Damit lassen sich ganze Beweise elegant als Inferenzbaumeaufschreiben51:

X ⇒ Y X⇒ B

Y Z∧E

Y ∧ Z

I Angelehnt an diese Notation werden wir die Regeln der Typinferenznotieren.

51Dabei stehen B bzw. E fur Beseitigungs- bzw. Einfugeregeln.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 409

Page 410: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Regeln fur die Typinferenz · 13.4

13.4 Regeln fur die Typinferenz Applikation & Abstraktion

I In diesem Kapitel stehen die Ti fur noch unbekannte Typen (i ∈ N).Die Typvariablen (α, β, ...) verwenden wir dann fur polymorphe Typen.

I Seien f , e beliebige λ-Ausdrucke; x eine Variable.

Applikation Die Inferenzregel fur die Funktionsapplikation f e lautet:

f :: T1 → T2 e :: T1@

f e :: T2

I In einer Applikation f e muss f einen Typ haben, der den Typ T1 desArguments auf einen Ergebnistyp T2 abbildet.

I T2 ist dann der Typ des Ausdrucks f e.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 410

Page 411: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Regeln fur die Typinferenz · 13.4

Abstraktion Fur die Abstraktion λx . e lautet die Regel:

e :: T2λx :: T1

λx . e :: T1 → T2

I Unter der Annahme52 daß die alle in e freien x den Typ T1 haben, iste :: T2.

I Die Funktion λx . e liefert dann fur ein Argument vom Typ T1 Werte vomTyp T2 des Funktionsrumpfes e.

52diese notieren wir etwas unorthodox rechts neben dem Bruchstrich.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 411

Page 412: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Regeln fur die Typinferenz · 13.4

Beispiel Bestimme den Typ T0 von const = λx . λy . x :

I Fur eine Abstraktion λx ... verwenden wir immer die λ-Regel:

λy . x :: T2λx :: T1

λx . λy . x :: T0

• Daraus lernen wir schon:T0 = T1 → T2,

• allerdings bleibt die Frage was T2 furein Typ sein soll.

I Auch dafur wenden wir die λ-Regel an, und schreiben sie daruber:

x :: T1λy :: T3

λy . x :: T2λx :: T1

λx . λy . x :: T0

• Dabei wissen wir schon aus derunteren Regel, daß x den Typ T1

haben muss!

• Neu lernen wir T2 = T3 → T1.

I Einsetzen der Gleichung fur T2 in die Gleichung fur T0 liefert:

T0 = T1 → T3 → T1

I Diese Erkenntnis gilt offenbar fur alle Typen T1 und T3:

const :: ∀α β. α→ β → α

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 412

Page 413: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Regeln fur die Typinferenz · 13.4

NotationI Es ist nicht notig die einzelnen Teilausdrucke bei jedem Schritt

hinzuschreiben:

x :: T1λy :: T3

T2λx :: T1

T0

statt

x :: T1λy :: T3

λy . x :: T2λx :: T1

λx . λy . x :: T0

• An der Struktur des Inferenzbaumes lasst sich die Struktur des Ausdrucksablesen — es ist der AST mit der Wurzel unten.

I Analog zu λx y z . e = λx . λy . λz . e fassen wir Abstraktionen oftzusammen: Fur λx y . x also

x :: T1λx :: T1, y :: T2

T0

statt

x :: T1λy :: T3

T2λx :: T1

T0

• Daraus lesen wir direkt ab: T0 = T1 → T2 → T1.• Offensichtlich sparen wir uns eine Typvariable — und auch Rechenarbeit.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 413

Page 414: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Regeln fur die Typinferenz · 13.4

Beispiel Typisierung von λx f . f x :

1. Zuerst konstruieren wir den Inferenzbaum: (rechts der AST zum Vergleich)

f :: T2 x :: T1@

T3λx :: T1, f :: T2

T0λx

λf

@

f x

•~

Wichtig: An alle durch das gleiche Lambda gebundenen Variablen diegleiche Typvariable schreiben!

2. Dann fangen wir unten (bei der Wurzel T0) an, Gleichungen abzulesen:

T0 =T1 → T2 → T3 aus der λ-RegelT2 =T1 → T3 aus der @-Regel

3. Einsetzen in T0 liefert: T0 = T1 → (T1 → T3)→ T3.

4. Allquantifizieren liefert: λx f . f x :: ∀α β. α→ (α→ β)→ β.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 414

Page 415: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Regeln fur die Typinferenz · 13.4

Beispiel Die Typisierung von S = λf g x . f x (g x):

I Wir konstruieren den Inferenzbaum (rechts nochmal der AST zum Vergleich)

f :: T1 x :: T3@

T5

g :: T2 x :: T3@

T6@

T4λf :: T1, g :: T2, x :: T3

T0 λf g x

@

@

f x

@

g x

I lesen abT0 =T1 → T2 → T3 → T4

T5 =T6 → T4

T1 =T3 → T5

T2 =T3 → T6

I setzen ein

T0 = (T3 → T5)→ (T3 → T6)→ T3 → T4

= (T3 → T6 → T4)→ (T3 → T6)→ T3 → T4

I und allquantifizieren:

S :: ∀α β γ. (α→ β → γ)→ (α→ β)→ α→ γStefan Klinger · DBIS Informatik 2 · Sommer 2016 415

Page 416: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Regeln fur die Typinferenz · 13.4

Beispiel Innere Abstraktion und Namensuberdeckung: λx y . x (λx . x y)

x :: T1

x :: T5 y :: T2@

T6λx :: T5

T4@

T3λx :: T1, y :: T2

T0

liefert

T0 =T1 → T2 → T3

T1 =T4 → T3

T4 =T5 → T6

T5 =T2 → T6

~

Wo genau kommen die Typen Ti der einzelnen Variablen her?

I Dann nur noch einsetzen und allquantifizieren:

T0 = ... = (((T2 → T6)→ T6)→ T3)→ T2 → T3

λx y . x (λx . x y) :: ∀α β γ. (((α→ β)→ β)→ γ)→ α→ γ

1 Prelude> :t \x y -> x (\x -> x y) — Man kann ja mal fragen2 \x y -> x (\x -> x y) :: (((r2 -> r1) -> r1) -> r) -> r2 -> r

3 — Eigentlich: ∀r r1 r2...., der GHC lasst den Allquantor leider weg.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 416

Page 417: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Unifikation von Typen · 13.5

13.5 Unifikation von Typen

I Manchmal erhalten wir mehrere Gleichungen fur die selbe Typvariable.

Beispiel twice = λf x . f (f x)

f :: T1

f :: T1 x :: T2@

T4@

T3λf :: T1, x :: T2

T0

T0 = T1 → T2 → T3 T1 = T2 → T4

T1 = T4 → T3

I Zunachst konstruieren wir den Inferenzbaum.

I Beide f sind durch das gleiche λ gebunden ⇒ gleiche Typvariable T1.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 417

Page 418: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Unifikation von Typen · 13.5

13.5 Unifikation von Typen

I Manchmal erhalten wir mehrere Gleichungen fur die selbe Typvariable.

Beispiel twice = λf x . f (f x)

f :: T1

f :: T1 x :: T2@

T4@

T3λf :: T1, x :: T2

T0

T0 = T1 → T2 → T3

T1 = T2 → T4

T1 = T4 → T3

I Die λ-Regel liefert eine Gleichung fur T0.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 418

Page 419: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Unifikation von Typen · 13.5

13.5 Unifikation von Typen

I Manchmal erhalten wir mehrere Gleichungen fur die selbe Typvariable.

Beispiel twice = λf x . f (f x)

f :: T1

f :: T1 x :: T2@

T4@

T3λf :: T1, x :: T2

T0

T0 = T1 → T2 → T3

T1 = T2 → T4

T1 = T4 → T3

I Die untere @-Regel liefert eine Gleichung fur T1.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 419

Page 420: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Unifikation von Typen · 13.5

13.5 Unifikation von Typen

I Manchmal erhalten wir mehrere Gleichungen fur die selbe Typvariable.

Beispiel twice = λf x . f (f x)

f :: T1

f :: T1 x :: T2@

T4@

T3λf :: T1, x :: T2

T0

T0 = T1 → T2 → T3 T1 = T2 → T4

T1 = T4 → T3

I Die obere @-Regel liefert eine weitere Gleichung fur T1.Die schreiben wir erst mal auf die Seite, und nicht in die linke Liste von Gleichungen!

Frage Zwei Gleichungen fur T1. Was bedeutet das?

Weiter auf Seite 422...Stefan Klinger · DBIS Informatik 2 · Sommer 2016 420

Page 421: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Unifikation von Typen · 13.5

Definition Gleichheit von Typen

Typen sind gleich, wenn

I sie primitiv sind und den gleichen Namen haben, oder

I wenn sie vom gleichen Konstruktor konstruiert wurden, und dieKomponenten gleich sind.

Beispiele

I Bool = Bool, Bool 6= Int, und Int 6= Integer

I [Char] = String — Tatsachlich ist String ein Alias fur [Char].

I (Int, [Char]) = (Int, String)

I Int→ Bool 6= Char→ Bool — weil Int 6= Char

Verwendung Aus T1 = T4 → T3 und T1 = T2 → T4 gewinnen wir alsozwei neue Gleichungen:

T4 = T2 und T3 = T4

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 421

Page 422: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Unifikation von Typen · 13.5

Beispiel Weiter mit twice = λf x . f (f x) von Seite 420:

f :: T1

f :: T1 x :: T2@

T4@

T3λf :: T1, x :: T2

T0

T0 = T1 → T2 → T3

X

T1 = T2 → T4

T1 = T4 → T3

X

T4 = T2

T4 = T2

X

T4 = T3

T3 = T2

X

T3 = T2

I Beide Gleichungen fur T1 beschreiben einen konstruierten Typ.• Der Typkonstruktor ist in beiden Fallen gleich: →• Fur die Gleichheit der Komponenten muss gelten: T4 = T2 und T3 = T4.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 422

Page 423: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Unifikation von Typen · 13.5

Beispiel Weiter mit twice = λf x . f (f x) von Seite 420:

f :: T1

f :: T1 x :: T2@

T4@

T3λf :: T1, x :: T2

T0

T0 = T1 → T2 → T3 XT1 = T2 → T4

T1 = T4 → T3

X

T4 = T2

T4 = T2 X

T4 = T3

T3 = T2

X

T3 = T2

I Die neuen Gleichungen schreiben wir ebenfalls auf die rechte Seite.• Reihenfolge und Anordnung sind dabei nicht wichtig.• Konvention: Wenn nur zwei Variablen gleichgesetzt werden, dann die

Variable mit dem großeren Index links vom Gleichzeichen schreiben.

I Damit haben wir die Gleichung T1 = T2 → T4 abgearbeitet.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 423

Page 424: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Unifikation von Typen · 13.5

Beispiel Weiter mit twice = λf x . f (f x) von Seite 420:

f :: T1

f :: T1 x :: T2@

T4@

T3λf :: T1, x :: T2

T0

T0 = T1 → T2 → T3 XT1 = T2 → T4

T1 = T4 → T3 XT4 = T2

T4 = T2

X

T4 = T3

T3 = T2

X

T3 = T2

I Da links noch keine Gleichung fur T4 steht, schieben wir eine der beidenGleichungen fur T4 nach links.

I Jetzt haben wir links und rechts eine Gleichung fur T4, daraus gewinnenwir T2 = T3.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 424

Page 425: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Unifikation von Typen · 13.5

Beispiel Weiter mit twice = λf x . f (f x) von Seite 420:

f :: T1

f :: T1 x :: T2@

T4@

T3λf :: T1, x :: T2

T0

T0 = T1 → T2 → T3 XT1 = T2 → T4

T1 = T4 → T3 XT4 = T2

T4 = T2 XT4 = T3

T3 = T2 X

T3 = T2

I Da links noch keine Gleichung fur T3 steht, schieben wir die neueGleichung ebenfalls nach links.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 425

Page 426: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Unifikation von Typen · 13.5

Beispiel Weiter mit twice = λf x . f (f x) von Seite 420:

f :: T1

f :: T1 x :: T2@

T4@

T3λf :: T1, x :: T2

T0

T0 = T1 → T2 → T3 XT1 = T2 → T4

T1 = T4 → T3 XT4 = T2

T4 = T2 XT4 = T3

T3 = T2 XT3 = T2

I Wir sind fertig sobald rechts keine Gleichungen mehr stehen,

I und alle Inferenzregeln abgearbeitet wurden.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 426

Page 427: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Unifikation von Typen · 13.5

Beispiel Weiter mit twice = λf x . f (f x) von Seite 420:

f :: T1

f :: T1 x :: T2@

T4@

T3λf :: T1, x :: T2

T0

T0 = T1 → T2 → T3 XT1 = T2 → T4

T1 = T4 → T3 XT4 = T2

T4 = T2 XT4 = T3

T3 = T2 XT3 = T2

I Einsetzen in die Gleichung fur T0 liefert T0 = (T2 → T2)→ T2 → T2.

I Allquantifizieren liefert das Ergebnis:

twice :: ∀α. (α→ α)→ α→ α

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 427

Page 428: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Unifikation von Typen · 13.5

Beispiel Typisierung von E = λf x y . f x (f y x).

f :: T1 x :: T2@

T5

f :: T1 y :: T3@

T7 x :: T2@

T6@

T4λf :: T1, x :: T2, y :: T3

T0

T0 = T1 → T2 → T3 → T4 XT1 = T3 → T7

T5 = T6 → T4 XT3 = T2

T1 = T2 → T5 XT7 = T5

T7 = T2 → T6 XT5 = T2 → T6

T3 = T2 XT6 = T2

T6 = T2 XT6 = T4

T4 = T2 XT4 = T2

E :: ∀α. (α→ α→ α)→ α→ α→ α

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 428

Page 429: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Typfehler · 13.6

13.6 Typfehler

I Nicht immer lasst sich ein λ-Ausdruck typisieren.

Beispiel λf . f (λx . f )

1 Prelude> :t \f -> f (\x -> f)

2 <interactive>:1:17:

3 Occurs check: cannot construct the infinite type:

4 r2 ~ (r1 -> r2) -> r

f :: T1

f :: T1λx :: T4

T3@

T2λf :: T1

T0

T0 = T1 → T2

T1 = T3 → T2

T3 = T4 → T1

I Beim Einsetzten von T3 in die Gleichung fur T1 stoßt man auf den Zykel

T1 = (T4 → T1)→ T2

⇒ Typfehler wegen unendlicher Typen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 429

Page 430: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Typfehler · 13.6

Innere Typfehler ...die sieht man nicht gleich

I Damit ein Ausdruck typkorrekt ist, mussen alle seine Teilausdrucketypkorrekt sein.

Beispiel Die Typisierung von E = λx . (λy . x) (λf . f f ).

x :: T1λy :: T4

T3

f :: T6 f :: T6@

T7λf :: T6

T5@

T2λx :: T1

T0

T0 = T1 → T2 XT3 = T4 → T1

T3 = T5 → T2 XT5 = T4

T5 = T4 XT2 = T1

T2 = T1 XT5 = T6 → T7

T4 = T6 → T7 XT4 = T6 → T7

T6 = T6 → T7

I Einsetzen liefert T0 = T1 → T2 = T1 → T1 und damit E :: ∀α. α→ α.

I Das ist Falsch weil λf . f f schon einen Typfehler hat: T6.• Tatsachlich mussen wir zum Schluß alle Typvariablen durch vollstandiges

Einsetzen uberprufen.• Beim Einsetzen in T3 fallt der Fehler dann auf.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 430

Page 431: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Typfehler · 13.6

I In den nachfolgenden Abschnitten werden wir weitere Typfehler sehen,hier nur ein Uberblick:• Unendlicher Typ, z.B.:

T1 = T1 → T2 oder T3 = [T3]

• Verschiedene primitive Typen, z.B.:

Int = Char

• Inkompatible Typkonstruktoren, z.B.:

(T1,T2) = [T3] oder Int = T4 → T5

~

Vorsicht Nicht alles was unpassend aussieht ist auch ein Fehler.

Frage Was bedeutet das folgende Gleichungssystem?

T0 = T1 → T2 T0 = T3 → T4 → T5

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 431

Page 432: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Vordefinierte Funktionen und Konstanten · 13.7

13.7 Vordefinierte Funktionen und KonstantenI Unser λ-Kalkul erlaubt die Verwendung von Konstanten, also etwa

vordefinierten Werten oder Funktionen mit ihrem jeweiligen Typ.• "hello" :: [Char]• + :: Int→ Int→ Int• foldr :: ∀α β. (α→ β → β)→ β → [α]→ β

I Wenn der Ausdruck eine Konstante enhalt, fugen wir den entsprechendenTyp in das Gleichungssystem ein.

I~

Dabei mussen wir zwischen monomorphen und polymorphenTypen unterscheiden.

Definition Monomorphe Typen

I Ein Typ heißt monomorph gdw. er keinen Allquantor enthalt.

I Damit ist monomorph das genaue Gegenteil von polymorph.

Wir werden Ad-hoc Polymorphie nicht besprechen, d.h. dass uns Typklassen und Typender Form C α⇒ α→ Int nicht begegnen werden.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 432

Page 433: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Vordefinierte Funktionen und Konstanten · 13.7

Die Verwendung monomorpher Konstanten

I Beispiele fur Konstanten mit monomorphem Typ:42 :: Int, True :: Bool, even :: Int→ Bool, ....

I Deren Typ kopieren wir einfach als erstes in das Gleichungssystem.

Beispiel Der Typ von λf . even (f 42).

even :: T3

f :: T1 42 :: T5@

T4@

T2λf :: T1

T0

T3 = Int→ Bool XT3 = T4 → T2

T5 = Int XT4 = Int

T0 = T1 → T2 XT2 = Bool

T4 = Int

T2 = Bool

T1 = T5 → T4

T0 = T1 → T2 = (T5 → T4)→ T2 = (Int→ Int)→ Bool enthalt keinefreien Typvariablen uber die allquantifiziert werden konnte.

λf . even (f 42) :: (Int→ Int)→ Bool

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 433

Page 434: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Vordefinierte Funktionen und Konstanten · 13.7

Beispiel Der Typ von λf . f True.

f :: T1 True :: T3@

T2λf :: T1

T0

T3 = Bool

T0 = T1 → T2

T1 = T3 → T2

I Einsetzen liefert T0 = ... = (Bool→ T2)→ T2.

I Bool ist eine Typkonstante, uber T2 mussen wir allquantifizieren:

λf . f True :: ∀α. (Bool→ α)→ α

Dieser Ausdruck hat also polymorphen Typ, und enthalt Typkonstanten.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 434

Page 435: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Polymorphie verwenden · 13.8

13.8 Polymorphie verwenden

I Konstanten mit polymorphem Typ sind z.B. id, map, length, ...

I Haskell stellt solche Typen mit freien Typvariablen dar, welcheimplizit durch einen Allquantor gebunden sind:

1 Prelude> :t id

2 id :: α -> α —eigentlich id :: ∀α. α→ α3 Prelude> :t map

4 map :: (α -> β) -> [α] -> [β] —eigentlich map :: ∀α β. (α→ β)→ [α]→ [β]

I Bei der Verwendung polymorpher Konstanten werden dieallquantifizierten Variablen durch konkrete Typen instanziiert.

Instanziierung Fur die Typinferenz heißt das, dass fur jede Verwendungdie allquantifizierten Typvariablen konsistent durch neue Typvariablenersetzt werden:

const :: ∀α β. α→ β → α instanziiert z.B. zu T23 → T24 → T23

~

Dabei stehen die Ti fur neue monomorphe unbekannte Typen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 435

Page 436: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Polymorphie verwenden · 13.8

Beispiel Gegeben sei id :: ∀α. α→ α. Was ist der Typ von id id ?

id :: T1 id :: T2@

T0

T1 = T3 → T3 XT1 = T2 → T0

T2 = T4 → T4 XT3 = T2

T3 = T2 XT3 = T0

T0 = T4 → T4 XT2 = T0

I Dabei sind T1 und T2 potentiell verschiedene Instanzen despolymorphen Typs ∀α. α→ α, erkennbar an den (noch unbekannten)Typen T3 und T4..

I Allquantifizieren von T0 = T4 → T4 liefert id id :: ∀α. α→ α.

Wichtig Dies ist die Kernidee der Polymorphie:

I Die “vielgestaltigen Teile” eines polymorphen Typs werden durchallquantifizierte Variablen markiert.

I Bei jeder Verwendung nimmt eine polymorphe Funktion einenpotentiell anderen monomorphen Typ an, indem die allquantifiziertenVariablen konkretisiert werden.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 436

Page 437: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Polymorphie verwenden · 13.8

Beispiel Bei falscher monomorpher53 Verwendung von id wurden wireinen Typfehler erhalten:

id :: T1 id :: T1@

T0

T1 = T1 → T0 —unendlicher Typ!

Erinnerung “Polymorphie” bedeutet Vielgestaltigkeit.

I Hier haben wir die Funktion in nur einer Gestalt, namlich T1 verwendet.

I Auf der vorherigen Folie haben wir durch die Verwendungunterschiedlicher Typvariablen T1 und T2 verschiedene Typen erlaubt.

53d.h., ohne Instanziierung mit frischen Typvariablen, also gerade nicht polymorphStefan Klinger · DBIS Informatik 2 · Sommer 2016 437

Page 438: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Polymorphie verwenden · 13.8

Beispiel Der Typ von const 42 const.

const :: T2 42 :: T3@

T1 const :: T4@

T0

T2 = T5 → T6 → T5 XT2 = T3 → T1

T3 = Int XT5 = T3

T4 = T7 → T8 → T7 XT1 = T6 → T5

T1 = T4 → T0 XT6 = T4

T5 = T3 XT5 = T0

T6 = T4 XT3 = T0

T0 = Int XT0 = Int

I Damit ist const 42 const :: Int.I Interessant: Die jeweiligen konkreten Typen von const:

• T2 = T5 → T6 → T5 = T3 → T4 → T3 = Int→ (T7 → T8 → T7)→ Int• T4 = T7 → T8 → T7

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 438

Page 439: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Polymorphie verwenden · 13.8

Beispiel Was ist der Typ von map length "foo" ?Gegeben seien "foo" :: String, length :: ∀α. [α]→ Int, sowiemap :: ∀αβ. (α→ β)→ [α]→ [β].

map :: T2 length :: T3@

T1 "foo" :: T4@

T0

T2 = (T5 → T6)→ [T5]→ [T6] XT2 = T3 → T1

T3 = [T7]→ Int XT3 = T5 → T6

T4 = [Char] XT1 = [T5]→ [T6]

T1 = T4 → T0 XT5 = [T7]

T5 = [T7] XT6 = Int

T6 = Int XT4 = [T5]

T0 = [T6] XT0 = [T6]

T5 = Char

I Typfehler in T5, da der primitive Typ Char nicht mit demkonstruierten Typ [T7] unifiziert werden kann.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 439

Page 440: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

13.9 let-Polymorphie

Das let...in-Konstrukt scheint auf den ersten Blick redundant zu sein, daman die Variablenbindung auch uber eine λ-Abstraktion erreichen kann:

let x = m in e?≡ (λx . e) m

I Ohne Rekursion gilt diese Aquivalenz im untypisierten λ-Kalkul,allerdings verhalten sie sich unterschiedlich bezuglich ihrer Typisierung.

• Wir definieren also andere Typregeln fur let...in als fur die λ-Abstraktion.

I Ausblick: Mit dem bisher beschriebenen Typsystem fur den λ-Kalkulohne let lasst sich kein typkorrekter Fixpunkt-Kombinator formulieren.

• Dieser sogenannte “simply typed λ-calculus” (auch als λ→ bezeichnet) istsogar stark normalisierend, d.h., jedes in λ→ geschriebene Programmterminiert54. Damit ist λ→ leider nicht Turing-Vollstandig.

• Um rekursive Funktionen definieren zu konnen, erlauben wir spater auch nochrekursive Definitionen mit let, cf. Seite 448.

54W. W. Tait. Intensional Interpretations of Functionals of Finite Type I. JSL 32(2), 1967.http://www.jstor.org/stable/pdf/2271658.pdf

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 440

Page 441: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

Beispiel In dem Ausdruck (wieder: length :: ∀α. [α]→ Int, "foo" :: String)

id length (id "foo")

wird id :: ∀α. α→ α verschieden instanziiert.

I Aber wo genau kommt dieses id her?I Konnen wir selber Ausdrucke schreiben die eine polymorphe Funktion

einfuhren und verwenden?• Bisher hatten wir ja erst am Ende der Typinferenz allquantifiziert, und• verwendete polymorphe Terme waren immer vordefinierte Konstanten.

I Der erste Ansatz

(λf . f length (f "foo")) (λx . x)

fuhrt zu einem Typfehler der Form

T5 = [T9]→ Int ∧ T5 = [Char]

Fragen Warum ist das ein Typfehler? Warum tritt genau dieser Typfehlerauf? Und was ist das grundlegende Problem?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 441

Page 442: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

let fuhrt polymorphe Typen ein

I Der Kern des Problems liegt in der λ-Regel:

e :: T2λx :: T1

λx . e :: T1 → T2

Sie erzwingt den gleichen monomorphen Typ T1 fur alle in e freienVorkommen von x .• Es gibt (deutlich komplexere) Typsysteme, die diese Einfschrankung

aufweichen.

I Dagegen erlaubt let die Definition von lokalen, polymorphenAusdrucken, die dann zu unterschiedlichen konkreten Typen instanziiertwerden konnen:

let x = m in e

erlaubt die polymorphe Verwendung von x in e.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 442

Page 443: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

Beispiel let f = λx . x in f length (f "foo")

x :: T2λx :: T2

f :: T1

f :: T5 length :: T6@

T4

f :: T8 "foo" :: T9@

T7@

T3let f

:: ∀α. α→ α

T0

I Gegeben sind

length :: ∀α. [α]→ Int

"foo" :: String

I Durch Instanziieren erhalten wir Typgleichungenfur T6 und T9.

T6 = [T10]→ Int

T9 = [Char]

T1 = T2 → T2

T5 = T11 → T11

T8 = T12 → T12

T3 = T0

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 443

Page 444: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

Beispiel let f = λx . x in f length (f "foo")

x :: T2λx :: T2

f :: T1

f :: T5 length :: T6@

T4

f :: T8 "foo" :: T9@

T7@

T3let f

:: ∀α. α→ α

T0

I Die let-gebundene Variable f wird im in-Zweigpolymorph verwendet.⇒ verschiedene Typvariablen T5, T8.

I Fur T5 und T8 fehlt uns noch der polymorphe Typvon f .⇒ Den mussen wir zuerst bestimmen...

T6 = [T10]→ Int

T9 = [Char]

T1 = T2 → T2

T5 = T11 → T11

T8 = T12 → T12

T3 = T0

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 444

Page 445: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

Beispiel let f = λx . x in f length (f "foo")

x :: T2λx :: T2

f :: T1

f :: T5 length :: T6@

T4

f :: T8 "foo" :: T9@

T7@

T3let f :: ∀α. α→ α

T0

I Vollstandige Typinferenz fur den let-Zweig liefert(hier: durch nur eine neue Gleichung) T1.

I Allquantifizieren der freien Typvariablen ergibt denpolymorphen Typ von f im in-Zweig...

f :: ∀α. α→ α

I ...der dann zu T5 und T8 instanziiert wird.

T6 = [T10]→ Int

T9 = [Char]

T1 = T2 → T2

T5 = T11 → T11

T8 = T12 → T12

T3 = T0

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 445

Page 446: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

Beispiel let f = λx . x in f length (f "foo")

x :: T2λx :: T2

f :: T1

f :: T5 length :: T6@

T4

f :: T8 "foo" :: T9@

T7@

T3let f :: ∀α. α→ α

T0

I Vollstandige Typinferenz fur den let-Zweig liefert(hier: durch nur eine neue Gleichung) T1.

I Allquantifizieren der freien Typvariablen ergibt denpolymorphen Typ von f im in-Zweig...

f :: ∀α. α→ α

I ...der dann zu T5 und T8 instanziiert wird.

T6 = [T10]→ Int

T9 = [Char]

T1 = T2 → T2

T5 = T11 → T11

T8 = T12 → T12

T3 = T0

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 446

Page 447: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

Beispiel let f = λx . x in f length (f "foo")

x :: T2λx :: T2

f :: T1

f :: T5 length :: T6@

T4

f :: T8 "foo" :: T9@

T7@

T3let f :: ∀α. α→ α

T0

I Der Typ des in-Zweiges ist immer auch der Typdes gesamten let...in-Ausdrucks.

I Mit diesen Gleichungen wird die Typinferenz imin-Zweig fortgesetzt, und liefert schließlich

T0 = Int

T5 = ([Char]→ Int)→ [Char]→ Int

T8 = [Char]→ [Char]

T6 = [T10]→ Int

T9 = [Char]

T1 = T2 → T2

T5 = T11 → T11

T8 = T12 → T12

T3 = T0

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 447

Page 448: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

let-Rekursion

I Wir verwenden das let-Konstrukt auch, um rekursive Funktionen zudefinieren55, cf. Seite 440.

let f = e1 f in e2 f

I Damit die Typisierung der rekursiven Definition von f gelingen kann,mussen wir f im let-Zweig einen monomorphen Typ T1 geben.

I Nur im in-Zweig kann f polymorph verwendet werden, und bekommtbei jeder Verwendung eine neue Typvariable, hier T5.

e1 :: T2 f :: T1@

f :: T1

e2 :: T4 f :: T5@

T3let f

T0

55Hier steht ei f allgemein fur einen beliebigen λ-Ausdruck der f frei enthalt.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 448

Page 449: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

Beispiel let g = λx . cons x (g x) in g . Mit cons :: ∀α. α→ [α]→ [α].

cons :: T5 x :: T2@

T4

g :: T1 x :: T2@

T6@

T3λx :: T2

g :: T1 g :: T7let g

T0

I Im let-Zweig bekommt g den monomorphen Typ T1.

I Typinferenz, von unten bis in den let-Zweig, liefert T1 = T2 → [T2].

I Im in-Zweig verwenden wir g polymorph. Allquantifizieren von T1 liefert

g :: ∀α. α→ [α]

was zu T7 = T9 → [T9] instanziiert wird.

I Mit T7 = T0 und Allquantifizieren der freien Typvariablen folgt

let g = λx . cons x (g x) in g :: ∀α. α→ [α]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 449

Page 450: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

Gebundene Typvariablen

I Der durch let-eingefuhrte Term kann Variablen enthalten, die unterhalbdes let gebunden wurden

I Deshalb konnen Typvariablen aus der Gleichungfur Ty in der Gleichung fur Tx auftauchen.

Tx = Ta → Tc

Ty = Tb → Tc~

Diese durfen nicht allquantifiziert werden!

I Falls Ta nicht ebenfalls in Ty auftaucht, gilt hier:

x :: ∀α. α→ Tc

y :: Ty···

x :: Tx

···let x

···λy :: Ty

T0

Folgerung Nach der Typinferenz fur den let-Zweig mussen dieGleichungen fur alle unterhalb (durch λ oder let) gebundenen Typvariablenvollstandig eingesetzt werden. Dann erst kennen wir die freienTypvariablen, die allquantifiziert werden mussen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 450

Page 451: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

Beispiel λx . let xs = cons x xs in xs. Mit cons :: ∀α. α→ [α]→ [α].

cons :: T5 x :: T1@

T4 xs :: T3@

xs :: T3 xs :: T6let xs

T2λx :: T1

T0

I Typinferenz von unten bis in den let-Zweigliefert die Gleichungen rechts, also T3 = [T1].

~

Obacht Die Typvariable T1 ist außerhalbdes let gebunden. Der Typ von xs ist nichtpolymorph in T1. Allquantifizieren liefert also“nur” xs :: [T1] und damit T6 = [T1].

T5 = T7 → [T7]→ [T7]

T0 = T1 → T2

T6 = T2

T4 = T3 → T3

T7 = T1

T3 = [T7]

Der Rest der Typinferenz verlauft wie gewohnt, und liefert ∀α. α→ [α].

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 451

Page 452: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

Aufschlussreich ist der Vergleich der beiden vorangegangenen Beispiele:

I let g = λx . cons x (g x) in g cf. Seite 449

• Hier ist g eine Funktion, die eine Liste bestehend aus Wiederholungen ihresArguments erzeugt.

• g kann auf Elemente beliebigen Typs angewandt werden, ist also polymorph.

I λx . let xs = cons x xs in xs cf. Seite 451

• Auch hier erzeugt xs eine Liste bestehend aus Wiederholungen von x .Allerdings steht das zu verwendende Element x , und damit sein Typ, bei derDefinition von xs schon fest.

• Damit ist xs monomorph.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 452

Page 453: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

Inferenzregeln fur let...in

Typinferenz von m. Jedes freie Vorkommenvon x hat den gleichen Typ Tj .···

x :: Tj

Typinferenz von e. Neue Typvariablenfur jedes freie Vorkommen von x .

···e :: Ti

let xlet x = m in e :: Ti

I Im let-Zweig wird x monomorph verwendet.• Alle freien Vorkommen von x in m bekommen den gleichen Typ.

I Typinferenz von m liefert Gleichung fur Tj .• Allquantifizieren der freien56 Typvariablen liefert polymorphen Typ von x .

I Im in-Zweig wird x polymorph verwendet:• Jedes freie Vorkommen von x in e wird mit neuen Typvariablen instanziiert.

I Typinferenz von e liefert dann den Typ des gesamten let-Ausdrucks.

56nicht ausserhalb des let gebundenen, cf. Seite 450Stefan Klinger · DBIS Informatik 2 · Sommer 2016 453

Page 454: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

Beispiel λf . let g = λy . f True in g g .

f :: T1 True :: Bool@

T5λy :: T4

g :: T3

g :: T7 g :: T8@

T6let g :: ∀α. α→ T5

T2λf :: T1

T0

I Typinferenz von unten bis in den let-Zweig liefert g :: T4 → T5.

I Ausserhalb gebunden ist f :: Bool→ T5.

I Damit ist T5 im Typ von g gebunden, nur T4 ist frei. Im in-Zweig ist

g :: ∀α. α→ T5

I Insgesamt liefert die Typinferenz dann

λf . let g = λy . f True in g g :: ∀τ. (Bool→ τ)→ τ

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 454

Page 455: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

Beispiel foo = λx . let f = (,) x in f f Mit (,) :: ∀α β. α→ β → (α, β).

(,) :: T4 x :: T1@

f :: T3

f :: T6 f :: T7@

T5let f :: ∀α. α→ (T8, α)

T2λx :: T1

T0

T4 = T8 → T9 → (T8,T9) XT4 = T1 → T3

T0 = T1 → T2 XT8 = T1

T5 = T2 XT3 = T9 → (T8,T9)

T8 = T1

T3 = T9 → (T8,T9)

T3 = T9 → (T1,T9) und x :: T1 gebunden, also f :: ∀α. α→ (T1, α)

T6 = T10 → (T1,T10) XT6 = T7 → T5

T7 = T11 → (T1,T11) XT10 = T7

T10 = T7 XT5 = (T1,T10)

T2 = (T1,T10) XT2 = (T1,T10)

T0 = ... = T1 → (T1,T11 → (T1,T11)) ⇒ foo :: ∀α β. α→ (α, β → (α, β))

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 455

Page 456: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz let-Polymorphie · 13.9

Beispiel λx . let c = λy . x in c c

x :: T1λy :: T4

c :: T3

c :: T6 c :: T7@

T5let c

T2λx :: T1

T0

T0 = T1 → T2

T5 = T2

T3 = T4 → T1

T3 = T4 → T1 und T0 = T1 → T2 also c :: ∀α. α→ T1

T6 = T8 → T1 XT6 = T7 → T5

T7 = T9 → T1 XT8 = T7

T8 = T7 XT5 = T1

T2 = T1 XT2 = T1

T0 = T1 → T2 = T1 → T1 ⇒ λx . let c = λy . x in c c :: ∀α. α→ α

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 456

Page 457: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Literatur · 13.10

13.10 Literatur

I Das in diesem Kapitel besprochene Typsystem ist als Hindley-MilnerTypsystem oder Hindley-Damas Typsystem bekannt57.• Luis Damas, Robin Milner. Principal Type-Schemes for Functional Programs.

1982.

I Haskell verwendet ein ahnliches System mit vielen Erweiterungen,insbesondere Typklassen.• Philip Wadler, Stephen Blott. How to make Ad-hoc Polymorphism less Ad

Hoc. 16th Symposium on Principles of Programming Languages. Austin,Texas, 1989. http://homepages.inf.ed.ac.uk/wadler/papers/class/class.ps.gz

I Es gibt viele verschiedene Typsysteme, mit ganz unterschiedlichenAuspragungen. Einen Uberblick verschafft• Benjamin C. Pierce. Types and Programming Languages.

ISBN 0-262-16209-1. http://www.cis.upenn.edu/~bcpierce/tapl/

57https://en.wikipedia.org/wiki/Hindley-Milner_type_systemStefan Klinger · DBIS Informatik 2 · Sommer 2016 457

Page 458: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Exkurs: Subtypen · 13.11

13.11 Exkurs: SubtypenDieser Abschnitt bezieht sich nicht auf Haskell, weil dieses keine Subtypen kennt.

Allgemein beschreibt die Subtyp-Relation S ≺ T eine Form derErsetzbarkeit: Ein Term des Typs S kann in jedem Kontext verwendetwerden, in dem ein Term vom Typ T erwartet wird.

e :: S S ≺ T≺

e :: T

I Dadurch konnen Werte verschiedene Typen annehmen (oben: e :: S unde :: T , es handelt sich also um eine Art der Polymorphie.

I Polymorphie in objekt-orientierten Sprachen bezieht sich meist aufKlassenhierarchien:

Amsel ≺ Vogel ≺ Tier

Unsere parametrische Polymorphie wird dort eher generische Programmierung genannt.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 458

Page 459: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Exkurs: Subtypen · 13.11

I Obacht: “Subtyp” bedeutet nicht einfach nur “Teilmenge”:

N ⊂ Q 6⇒ Int ≺ Double

Eine Methode foo(Double x) fuhrt evtl. eine Division auf x aus, die furInteger nicht unbedingt definiert ist.

I Vielmehr ist gemeint dass der Subtyp spezieller sein muss, undinsbesondere alle Fahigkeiten des Obertyps besitzt.

Das Liskov Substitutionsprinzip ist eine strenge Formulierung furSubtypen (die nicht von jeder Programmiersprache umgesetzt wird):

Sei φ eine fur alle Werte des Typ T beweisbare Eigenschaft, dann mussdiese auch fur alle Werte aller Subtypen von T gelten:

(x :: T ⇒ φ x) ⇒ (y :: S ∧ S ≺ T ⇒ φ y)

Grob: Wenn S ≺ T , dann konnen in einem Programm alle Objekte vom Typ Tdurch Objekte vom Typ S ersetzt werden, ohne das Programm zu verandern.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 459

Page 460: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Exkurs: Subtypen · 13.11

Ko- und Kontravarianz

Sei S ≺ T . Wie verhalten sich dann aus S und T konstruierte Typenzueinander?

I Sei K ein einstelliger Typkonstruktor. K heißt

kovariant wenn K S ≺ K T , also die Richtung erhalten bleibt,

kontravariant K S � K T , sich also die Richtung umkehrt,

invariant sonst (≺ ist eine partielle Ordnung auf Typen, die Beziehungkann also auch in keiner der beiden Richtungen bestehen).

I Fur mehrstellige Typkonstruktoren betrachtet man Varianz fur jede Stelleeinzeln (cf. Seite 462).

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 460

Page 461: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Exkurs: Subtypen · 13.11

Beispiel: Arrays

Seien String ≺ Object, Integer ≺ Object. Wie verhalten sich Arrays?

I Kovariant: String[] ≺ Object[] ? (Java macht das so)

• Eine Funktion die aus einem Object[] liest, wird auch mit einem Stringzufrieden sein, weil String ≺ Object.

• Was passiert hier:

1 String[] strings = new String[12];

2 Object[] objects = strings;

3 objects[0] = new Integer(1);

I Kontravariant: Object[] ≺ String[] ?• Das macht keinen Sinn: Jede Funktion die aus einem String[] liest, musste

mit einem beliebigen Object klar kommen.

⇒ Arrays sollten invariant sein. Java ist an dieser Stelle nicht typsicher!

Allgemein konnen read-only Datenstrukturen kovariant sein, write-onlyDatenstrukturen konnen kontravariant sein, read-write Datenstrukturensollten invariant sein.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 461

Page 462: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

13 · Typinferenz Exkurs: Subtypen · 13.11

Beispiel: Funktionen

f :: Df → Rf und g :: Dg → Rg

Frage Wann ist es typsicher eine Funktion f durch eine Funktion g zuersetzen, wann gilt also fur die Funktionstypen

Dg → Rg?≺ Df → Rf

Antwort Wenn g einen allgemeineren Typ akzeptiert, und einenspezielleren Typ zuruckgibt, also:

Dg�Df und Rg ≺ Rf

I Der Typkonstruktor → ist also kontravariant imersten, und kovariant im zweiten Argument.

Erinnerung: Wir ubergeben (schreiben) das Argument, undlesen das Ergebnis.

D1 → R1

g f fD2 → R2

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 462

Page 463: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14Monadische Berechnungen

Dieses Kapitel basiert großtenteils auf dem hervorragenden ArtikelTypeclassopedia58.

58Brent Yorgey. Typeclassopedia. https://wiki.haskell.org/Typeclassopedia

Page 464: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Referenzielle Transparenz · 14.1

14.1 Referenzielle Transparenz

I Reine FPLs bieten per Definition keine Seiteneffekte, z.B. keineveranderbaren Variablen.

I Die damit verbundenen Probleme bzgl. I/O haben wir am Anfang derVorlesung bereits angesprochen (Stichwort “Referenzielle Transparenz”):

1 (putStr "foo", putStr "bar") Die Reihenfolge der Auswertung derTeilausdrucke ist irrelevant.

1 getChar == getChar

2 random == random

3 getClockTime == getClockTime

Der Wert eines Ausdrucks hangtnur von den Werten seinerTeilausdrucke ab.

I Eine der herausragenden Eigenschaften von Haskell im Vergleich zuanderen FPLs ist die funktional saubere Integration von IO, undanderen effektbehafteten Berechnungen.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 464

Page 465: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Referenzielle Transparenz · 14.1

Losungsvorschlag: Zustand der Welt

I Eine “Variable” world :: World konnte den Zustand der Welt(Terminal, Festplatte, Netzwerkverbindungen, ...) beinhalten.

I Referenzielle Transparenz verbietet das Verandern von Variablen.Daher modellieren wir die Welt als zusatzliche Parameter derentsprechenden Funktionen.

Beispiel Fur IO mit einzelnen Zeichen konnte das so aussehen:

1 putChar :: Char → World → World

2 getChar :: World → (World, Char)

I Anwendung auf ein Terminal, auf dem schon der Text “hell” steht

1 putChar ’o’ hell_ _ hello_

I Angenommen auf stdin wartet der String "xy" darauf gelesen zuwerden:

1 getChar "xy" _ ( "y" , ’x’)

2 getChar "y" _ ( "" , ’y’)

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 465

Page 466: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Referenzielle Transparenz · 14.1

Beispiel Damit ließen sich auch komplexere Funktionen bauen:

1 getString :: World → (World,String)

2 getString w0

3 | stdin w0 = let (w1,c) = getChar w0 -- stdin :: World -> Bool

4 (w2,cs) = getString w1

5 in (w2, c:cs)

6 | otherwise = (w0,[])

I Dabei ist das explizite Weiterreichen der Welt arg umstandlich — undfehleranfallig.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 466

Page 467: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Referenzielle Transparenz · 14.1

~

Problem Das explizite Anwenden einer Funktion auf einen Zustandkann zu Inkonsistenzen fuhren:

1 clash w = ( putString "good" w , putString "evil" w )

Es kann nur eine Welt geben59 (das Terminal kann sich nichtverdoppeln). Der Zustand der Welt (world) ist nicht mehr konsistent,im besten Fall ist das Verhalten des Programmes undefiniert.

Deswegen suchen wir eine andere Losungund dazu mussen wir ein wenig ausholen...

59Wir ignorieren hier die theoretische Physik, u.a. David DeutschStefan Klinger · DBIS Informatik 2 · Sommer 2016 467

Page 468: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Typklassen · 14.2

14.2 Typklassen

Erinnerung Im Kapitel uber Typklassen (cf. Seite 299) haben wir gelerntwie man...

I ...Klassen definiert

1 class Eq α where

2 (==) :: α → α → Bool

3 (/=) :: α → α → Bool

• Hier steht α fur einen noch unbekannten Typen.

I ...und wie man einen Typ zur Instanz dieser Klasse erklart:

1 instance Eq Frac where

2 (x1 :/ y1) == (x2 :/ y2) = x1 * y2 == x2 * y1 — (==) :: Frac → Frac → Bool3 a /= b = not $ a == b — (/=) :: Frac → Frac → Bool

• Hier wird α an Frac gebunden, und die Typen der Funktionen entsprechendkonkretisiert.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 468

Page 469: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Typklassen · 14.2

Typkonstruktoren

Neu ist, dass man in Klassendefinitionen nicht nur von einem Typ, sondernsogar von einem Typkonstruktor abstrahieren kann:

I Bei der Definition der Klasse taucht dann die Variable t im Typ derFunktionen immer mit einem Argument auf, das den Typ vervollstandigt:

class ClassName t where

f :: t αg :: α→ t α

I Bei der Instanziierung eines Konstruktors C zu dieser Klasse werden dieTypen der Funktionen entsprechend konkretisiert:

instance ClassName C where

f = ... — :: C αg = ... — :: α→ C α

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 469

Page 470: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Typklassen · 14.2

Beispiel Benutzer eines aktuellen GHCi (ab Version 7.10) haben dasschon gesehen:

1 Prelude> :t foldr

2 foldr :: Foldable t ⇒ (α → β → β) → β → t α → β3

4 Prelude> :i Foldable

5 class Foldable t where

6 ...7 foldr :: (α → β → β) → β → t α → β8 foldl :: (β → α → β) → β → t α → β9 null :: t α → Bool

10 length :: t α → Int

11 elem :: Eq α ⇒ α → t α → Bool

12 ...

In der Prelude ist dann schon definiert:1 instance Foldable [] where — hier nur der Typkonstruktor [] fur Listen2 ...3 foldr = ... — :: (α→ β → β)→ β → [α]→ β4 ...

I Statt auf die Klasse Foldable einzugehen, besprechen wir einewesentlich einfachere...

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 470

Page 471: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Functor · 14.3

14.3 Functor (dt. Funktor)

1 class Functor f where

2 fmap :: (α → β) → f α → f β

I An den f α und f β sehen wir, dass f kein Typ, sondern einTypkonstruktor sein muss.

I fmap nimmt eine Funktion von α nach β, und liefert ein Funktion dief α nach f β abbildet.

fmap :: (α→ β)→ (f α→ f β)

• Fasst man f α als Container fur Werte vom Typ α auf, dann wird alsofmap g die Funktion g auf die Elemente des Containers anwenden.

• Abstrakter kann f auch einen Kontext reprasentieren, in dem die Funktion gverwendet wird.Das klingt sehr vage, bringt uns aber spater mehr: Wir legen uns nicht aufContainer fest.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 471

Page 472: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Functor · 14.3

Beispiele die den Functor als Container auffassen

I Listen1 instance Functor [] where

2 fmap _ [] = []

3 fmap g (x:xs) = g x : fmap g xs

4

5 *Main> fmap length ["hello","world","how","are","you"]

6 [5,5,3,3,3]

7 *Main> fmap length []

8 []

• Tatsachlich ist fmap fur Listen das gleiche wie map.

I Maybe

1 instance Functor Maybe where

2 fmap _ Nothing = Nothing

3 fmap g (Just x) = Just (g x)

4

5 *Main> fmap length Nothing

6 Nothing

7 *Main> fmap length $ Just "foo"

8 Just 3

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 472

Page 473: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Functor · 14.3

Was macht einen Functor aus?

I Meist kann man fmap einfach implementieren.I Aber das genugt noch nicht, um ein “echter” Functor im

mathematischen Sinn zu sein.• Ganz analog dazu, weshalb data Frac = Int :/ Int deriving Eq zwar

“irgendwie geht”, aber nicht “richtig” ist.

Gesetze Fur einen Functor mussen folgende Eigenschaften gelten:

1. fmap id ≡ id

2. fmap (g ◦ h) ≡ fmap g ◦ fmap h

Die Intuition dabei: fmap g verandert nur die Elemente des Containers,nicht den Container selbst.

Anmerkungen

I Man kann zeigen, dass fur jeden Typkonstruktor f hochstens eineInstanz von Functor existiert, die diese Gesetze erfullt.

I Ebenfalls gilt: Das erste Gesetz impliziert schon das zweite.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 473

Page 474: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Functor · 14.3

Kein Functor

Vorsicht Folgender Code ist typkorrekt (kompiliert, kann verwendetwerden), ist aber trotzdem kein richtiger Functor. Warum?

1 instance Functor [] where

2 fmap _ [] = []

3 fmap g (x:xs) = g x : g x : fmap g xs

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 474

Page 475: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Functor · 14.3

Value :: Type, Type :: Kind Die Art des Typs

Man kann fur einen Typ(konstruktor) sagen wieviele Argumente erbraucht, um zu einem “echten” Typ zu werden. Das ist sozusagen der Typdes Typs, engl.: the kind of type.

I Alles was Werte enthalt bekommt den Kind ∗, das sind die Konstantenauf Typebene.

Int :: ∗, [Char] :: ∗, Int→ Int :: ∗I Konstruktoren mit einem Typparameter haben den Kind ∗ → ∗, das sind

Funktionen auf Typebene mit einem (Typ-)Argument.

[ ] :: ∗ → ∗, Maybe :: ∗ → ∗I Konstruktoren mit 2 Typparametern haben dann den Kind ∗ → (∗ → ∗).

Either :: ∗ → ∗ → ∗, (,) :: ∗ → ∗ → ∗, (→) :: ∗ → ∗ → ∗I Es geht sogar:

1 Prelude> data Bar t = B (t Int)

2 Prelude> :k Bar

3 Bar :: (* -> *) -> *

1 Prelude> :t B (Just 4)

2 B (Just 4) :: Bar Maybe

3 Prelude> :t B [4]

4 B [4] :: Bar []

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 475

Page 476: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Functor · 14.3

Partiell angewandte Typkonstruktoren Typfehler auf Typebene

Naturlich kann man einen Typkonstruktor auch partiell anwenden:

1 Prelude> :k Either

2 Either :: * -> * -> *

3 Prelude> :k Either Int

4 Either Int :: * -> *

5 Prelude> :k Either Int Bool

6 Either Int Bool :: *

1 Prelude> :k (,)

2 (,) :: * -> * -> *

3 Prelude> :k (,) (Int -> Bool)

4 (,) (Int -> Bool) :: * -> *

5 Prelude> :k (,) (Int -> Bool) [Char]

6 (,) (Int -> Bool) [Char] :: *

I Bei der Klassendefinition wird der Kind des Parameters festgelegt:

1 Prelude> :i Functor — Altere GHC-Versionen zeigen den Kind nicht an.2 class Functor (f :: * -> *) where

3 fmap :: (a -> b) -> f a -> f b

I Bei der Instanziierung muss der Typ dann den gleichen Kind haben:

1 *Main> instance Functor Either where fmap = undefined

2 <interactive>:7:18:

3 Expecting one more argument to ‘Either’

4 The first argument of ‘Functor’ should have kind ‘* -> *’,

5 but ‘Either’ has kind ‘* -> * -> *’

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 476

Page 477: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Functor · 14.3

Fazit Fur Functor brauchen wir einen Typ vom Kind ∗ → ∗, also einenTypkonstruktor dem noch genau ein Typparameter fehlt.

Beispiele

1 instance Functor (Either τ) where — Dem Either τ fehlt noch der Typ fur Right.2 fmap f (Left l) = Left l

3 fmap f (Right x) = Right $ f x

4

5 instance Functor ((,) τ) where — eigentlich: Functor (τ,) where

6 fmap f (x,y) = (x, f y)

Frage Was ist der Typ von fmap bei diesen Instanziierungen?Erinnerung: class Functor f where fmap :: (α→ β) → f α → f β

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 477

Page 478: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Functor · 14.3

Functor ohne Container

Man kann sich vorstellen dass fmap eine Funktion innerhalb eines Kontextsf anwendet, also in den Kontext hebt (engl. lifting), ohne den Kontextzu verandern.

~

Beispiele Der Kontext muss dabei kein Container sein.

1 instance Functor ((→) τ) where — eigentlich: instance Functor (τ→) where

2 fmap = ... — wie geht das?

Dabei ist (τ →) der Typkonstruktor, welcher Funktionen von τ konstruiert.

Frage 1 Was ist der Typ von fmap bei dieser Instanziierung?Erinnerung: class Functor f where fmap :: (α→ β) → f α → f β

Frage 2 Was also ist fmap?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 478

Page 479: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Functor · 14.3

Antwort 1 fmap :: (α→ β)→ (τ → α)→ (τ → β)Das erhalt man durch einfaches Einsetzen von (τ →) fur f in dieDeklaration von fmap.

Antwort 2 Dieser Typ sollte bekannt vorkommen: Die Komposition.

I Setzen fmap = (◦)1 instance Functor ((→) τ) where

2 fmap = (.)

I Prufen die Funktor-Eigenschaft: Fur alle Funktionen g gilt

fmap id g _β

id ◦ g _β

λx . id (g x) _β

λx . g x ]η

g ≡ id g

Anwendung

1 *Main> :t length

2 length :: [a] → Int

3 *Main> :t (<3)

4 (<3) :: Int -> Bool

5 *Main> :t fmap (<3) length

6 fmap (<3) length :: [a] → Bool

I Aus [α]→ Int wird [α]→ Bool.

I In einer Funktion auf [α] haben wirden Ergebnistyp von Int in Boolverwandelt.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 479

Page 480: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Functor · 14.3

Mehr Argumente

I Bisher hatten wir Funktionen mit einem Argument uber einen Functorgemappt:

1 *Main> :t even — hier mit einfacherem Typ2 even :: Int → Bool

3

4 *Main> :t fmap even $ Just 42

5 fmap even $ Just 42 :: Maybe Bool

6

7 *Main> :t fmap even [1..]

8 fmap even [1..] :: [Bool]

9

10 *Main> :t fmap even length

11 fmap even length :: [α] → Bool

I Wichtig war der Inhalt derStruktur (Int), der als Argumentzur Funktion even passen muss.

I Die Struktur selbst war nichtweiter wichtig:Maybe, [·], ([α]→), ...

Frage Welche Typen sind bei Funktionen mit mehreren Argumenten zuerwarten? Beispiel: (unter der Annahme, dass (<) :: Int→ Int→ Bool)

fmap (<) [1, 2, 3]

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 480

Page 481: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Functor · 14.3

1 *Main> :t (<)

2 (<) :: Int → Int → Bool

3

4 *Main> :t fmap (<)

5 fmap (<) :: Functor f ⇒ f Int → f (Int → Bool)

6

7 *Main> :t fmap (<) $ Just 42

8 fmap (<) $ Just 42 :: Maybe (Int → Bool)

9

10 *Main> :t fmap (<) [1..]

11 fmap (<) [1..] :: [Int → Bool]

12

13 *Main> :t fmap (<) length

14 fmap (<) length :: [α] → Int → Bool

I Die Strukturen enthalten Funktionen. Also gerade das, was (+)angewendet auf einen Int liefert.

I Das ist nicht weiter uberraschend, aber ekelhaft, denn. . .

Offensichtliche Frage Wie wenden wir etwas vom Typ f (α→ β) auf etwasvom Typ f α an? Wie konnen wir so eine Funktion verwenden?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 481

Page 482: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Applicative Functor · 14.4

14.4 Applicative Functor (dt. Applikativer Funktor)

Brauchen eine Klasse um fur jede Struktur eine eigene Antwort zu finden:

1 class Functor f ⇒ Applicative f where

2 pure :: α → f α3 (<*>) :: f (α → β) → f α → f β — infixl 4; schreiben ~ in Formeln

Beobachtungen Applicative60 ist offenbar ein besonderer Functor.

I Mit pure kann man jeden Wert in die Struktur f heben.

I Der Typ der “Applikation” ~ ist sehr ahnlich zu $ :: (α→ β)→ α→ β.

I Jede Implementierung von ~ beantwortet die “offensichtliche Frage”(cf. letzte Folie) fur den instanziierten Typ.⇒ Fur einen applikativen Funktor ist diese Frage also geklart!

60Vor GHCi 7.10.2 muss das Modul Control.Applicative importiert werdenStefan Klinger · DBIS Informatik 2 · Sommer 2016 482

Page 483: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Applicative Functor · 14.4

Beispiel Maybe

1 instance Applicative Maybe where

2

3 pure = Just

4

5 Just f <*> u = fmap f u

6 Nothing <*> _ = Nothing

7 *Main> pure even <*> Just 23

8 Just False

9 *Main> Just (<) <*> Just 23 <*> Just 42

10 Just True

11 *Main> Just (<) <*> Nothing <*> Just 42

12 Nothing

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 483

Page 484: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Applicative Functor · 14.4

Beispiel Either τ ist auf ganz ahnliche Weise Applicative wie Maybe:

1 instance Applicative (Either τ) where

2

3 pure = Right

4

5 Right f <*> x = fmap f x

6 Left l <*> _ = Left l

7

8 *Main> Right (+) <*> Right 42 <*> Right 23

9 Right 65

10 *Main> Right (+) <*> Left "err" <*> Right 23

11 Left "error"

I Beide stellen “Berechnungen”dar, die fehlschlagen konnen.

I Either τ kann noch eine“Fehlermeldung” vom Typ τtragen, wo Maybe nurNothing liefert.

Frage Wie konnten Listen zur Instanz von Applicative erklart werden?Mit anderen Worten: Fur f = [ ] suchen wir Implementationen von

pure :: α→ f α

(~) :: f (α→ β)→ f α→ f β

Was soll das sein, [(+2), (+3), (+4)]~ [5, 6] ?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 484

Page 485: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Applicative Functor · 14.4

Plan A: Jeder mit jedem Die Comprehension Strategie

I Jede Funktion aus der linken Liste wird auf jedes Element aus der rechtenListe angewandt.

1 instance Applicative [] where

2 pure x = [x]

3 gs <*> xs = [ g x | g <- gs, x <- xs ]

4

5 *Main> [(+2),(+3),(+4)] <*> [5,6]

6 [7,8,8,9,9,10]

7 *Main> pure (*10) <*> [1..5]

8 [10,20,30,40,50]

9 *Main> pure (+) <*> [1..5] <*> pure 10

10 [11,12,13,14,15]

11 *Main> pure (+) <*> [1..5] <*> [10,20,30]

12 [11,21,31,12,22,32,13,23,33,14,24,34,15,25,35]

I Das implementiert “nicht-deterministische” Berechnungen:• Die Funktion + wird auf zwei Argumente angewendet, deren Wert nur

ungefahr bekannt ist.• Das erste Argument hat einen der Werte 1–5, das zweite einen der Werte 10,

20 oder 30.

I Auf diese Weise sind Listen standardmaßig als Applicative instanziiert.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 485

Page 486: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Applicative Functor · 14.4

Plan B: Jeder nur ein Kreuz Die ZipList Strategie

Eine andere Antwort auf die Frage: Was ist [(+2), (+3), (+4)]~ [5, 6] ?

I Jede Funktion aus der linken Liste wird dem “entsprechenden” Elementaus der rechten Liste zugeordnet. ⇒ zipWith ($).

1 instance Applicative [] where

2 pure = repeat

3 gs <*> xs = zipWith ($) gs xs

4

5 *Main> [(+2),(+3),(+4)] <*> [5,6]

6 [7,9]

7 *Main> pure (*10) <*> [1..5]

8 [10,20,30,40,50]

9 *Main> pure (+) <*> [1..5] <*> pure 10

10 [11,12,13,14,15]

11 *Main> pure (+) <*> [1..5] <*> [10,20,30]

12 [11,22,33]

Frage Welchen Effekt hat die Implementierung von pure?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 486

Page 487: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Applicative Functor · 14.4

Die Intuition hinter Applicative

Ganz abstrakt soll Applicative eine “Berechnung mit Effekt” auf funktionalsaubere Weise kapseln. Dabei ist der “Effekt” in f versteckt.

I Langfristiges Ziel: Das Kapseln von Seiteneffekten ohne die referenzielleTransparenz zu zerstoren.

I Wie abstrakt geht das denn? Oder: Wie unabhangig von der Strukturkonnen wir Berechnungen formulieren?

Frage Was ist das? (zur Erinnerung die Typen von ~ und pure anschauen)

pure (<)~ pure 23~ pure 42

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 487

Page 488: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Applicative Functor · 14.4

Antwort Das ist die Berechnung von (<) 23 42, allerdings in einer nochunbekannten Struktur:

1 *Main> pure (<) <*> pure 23 <*> pure 42

2 • Ambiguous type variable ‘f0’ arising from a use of ‘print’

3 prevents the constraint ‘(Show (f0 Bool))’ from being solved.

4 Probable fix: use a type annotation to specify what ‘f0’ should be.

...die Struktur ist tatsachlich unbekannt.

1 *Main> pure (<) <*> pure 23 <*> pure 42 :: Maybe Bool

2 Just True

3

4 *Main> pure (<) <*> pure 23 <*> pure 42 :: [Bool]

5 [True]

6

7 *Main> pure (<) <*> pure 23 <*> pure 42 :: Either Double Bool

8 Right True

9

10 *Main> pure (<) <*> pure 23 <*> pure 42 $ "wasauchimmer"

11 True — Was war hier der Funktor?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 488

Page 489: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Applicative Functor · 14.4

Anmerkung zur Fehlermeldung auf der vorigen Folie:

I Im interaktiven GHCi verhindert evtl. Type Defaulting (cf. Seite 330) daß wir eineFehlermeldung sehen, dabei wird f = IO gesetzt, cf. Seite 491.

I Sie Sehen den Fehler im GHCi, wenn Sie alle bisher besprochenen Klassen selbstimplementieren.

I Auch das Laden einer Datei mit der Definition

1 x = pure (<) <*> pure 23 <*> pure 42 — Ohne einen Typ anzugeben!

liefert aber die erwartete Fehlermeldung:

1 • Ambiguous type variable ‘f0’ arising from a use of ‘<*>’

2 prevents the constraint ‘(Applicative f0)’ from being solved.

3 Relevant bindings include

4 foo :: f0 Bool (bound at /tmp/foo.lhs:1:3)

5 Probable fix: use a type annotation to specify what ‘f0’ should be.

6 These potential instances exist:

7 instance Applicative IO -- Defined in ‘GHC.Base’

8 instance Applicative Maybe -- Defined in ‘GHC.Base’

9 instance Applicative ((->) a) -- Defined in ‘GHC.Base’

10 instance Monoid a => Applicative ((,) a) -- Defined in ‘GHC.Base’

11 instance Applicative [] -- Defined in ‘GHC.Base’

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 489

Page 490: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Ausblick: IO · 14.5

14.5 Ausblick: IOI Fest mit Compiler und Interpreter verwoben ist der Typkonstruktor

IO :: ∗ → ∗

• Tatsachlich kapselt IO den Zustand der Welt.• Auf diesen Zustand haben wir keinen Zugriff!

I Ein Wert vom Typ IO α stellt eine Berechnung mit Effekt dar, die einα produziert.

Bildlich: Ein IO α ist eine “Maschine” die ein α produziert.

Beispiel einen String auf das Terminal schreiben:

putStr :: String→ IO ()

1 Prelude> :t putStr "foo"

2 putStr "foo" :: IO () — Das ist also eine “Maschine” die ein () produziert.3 Prelude> putStr "foo"

4 fooPrelude> — Seiteneffekt: Vor dem Prompt wurde foo auf’s Terminal geschrieben.5 Prelude> it

6 () — Das Ergebnis der letzten Berechnung war ().

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 490

Page 491: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Ausblick: IO · 14.5

Der GHCi und IOFur jede Eingabe bestimmt der GHCi zunachste den Typ.

I Ist der Typ nicht IO α, dann wird das Ergebnis (mittels show) angezeigt.

1 Prelude> "hello world"

2 "hello world"

I Ist der Typ IO α, dann wird die IO-Aktion mit ihren Seiteneffektenausgefuhrt. Das Ergebnis wird an die Variable it :: α gebunden.• Das Ergebnis wird nicht angezeigt, falls α = (), oder keine Instanz von Show.

1 writeFile :: FilePath -> String -> IO () — Schreibe String in Datei2

3 Prelude> writeFile "foo.txt" "hello outside world"

4 Prelude> it

5 ()

• Sonst wird der Wert von it mittels show angezeigt.

1 readFile :: FilePath -> IO String — Lese String aus Datei2

3 Prelude> readFile "foo.txt" —readFile :: FilePath→ IO String4 "hello outside world"

5 Prelude> it

6 "hello outside world"

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 491

Page 492: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Ausblick: IO · 14.5

Obacht Wir konnen immer nur eine IO-Operation ausfuhren lassen:

1 Prelude> (putStrLn "foo", putStrLn "bar")

2

3 <interactive>:33:1: error:

4 • No instance for (Show (IO ())) arising from a use of ‘print’

5 • In a stmt of an interactive GHCi command: print it

I Es handelt sich nicht um eine IO-Operation, sondern um zwei.Sozusagen zwei Maschinen die etwas tun konnen, aber wir haben nichtfestgelegt welche wir ausfuhren wollen.

6 Prelude> :t (putStr "foo", putStr "bar")

7 (putStr "foo", putStr "bar") :: (IO (), IO ())

I Insbesondere ist der Typ nicht IO α, es wird also nichts ausgefuhrt (cf.vorige Folie).

I Analog dazu haben kompilierbare Programme eine Funktionmain :: IO ().

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 492

Page 493: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Ausblick: IO · 14.5

Vordefinierte IO-Operationen

I putStr, putStrLn :: String→ IO ()• Schreiben den ubergebenen String auf die Standardausgabe.• putStrLn fugt einen Zeilenumbruch an.

I getChar :: IO Char• Liest das nachste Zeichen von der Standardeingabe, und gibt es zuruck.

I getLine, getContents :: IO String• getLine liest die nachste Zeile,• getContents die gesamte Standardeingabe.

I writeFile :: FilePath→ String→ IO ()• Schreibt den ubergebenen String in die genannte Datei.

I readFile :: FilePath→ IO String• Liest die genannte Datei, und gibt den Inhalt als String zuruck.• Sollte nur auf Plain Text Dateien angewendet werden.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 493

Page 494: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Ausblick: IO · 14.5

IO ist ein Functor

1 Prelude> :i IO

2 ...3 instance Functor IO -- Defined in ‘GHC.Base’

I Damit konnen wir offensichtlich “gelesene” Daten verarbeiten:

1 fileSize :: FilePath -> IO Int

2 fileSize path = fmap length $ readFile path

3

4 Prelude> fileSize "foo.txt"

5 19

fileSize ist also eine Funktion, die einen Dateinamen konsumiert, undeine Maschine zuruckgibt die bei Ausfuhrung einen Int liefert.

I Weiteres Beispiel:

1 Prelude> filter (< 'd') ‘fmap‘ getLine

2 abracadabra — das ist meine Eingabe3 "abacaaba" — das Ergebnis der Berechnung wird mit show angezeigt

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 494

Page 495: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Ausblick: IO · 14.5

IO ist ein Applicative Functor

Aufgabe Schreibe eine Funktion die den Inhalt zweier Dateienkonkateniert:

I Konkatenieren ist einfach: (++) :: [α]→ [α]→ [α].

I Was passiert wenn wir das in den IO-Functor heben?

1 Prelude> :t (++) ‘fmap‘ readFile "foo.txt"

2 (++) ‘fmap‘ readFile "foo.txt" :: IO ([Char] -> [Char])

I An dieser Stelle kommen wir mit Functor alleine nicht weiter!• Wir brauchen eine Moglichkeit die Funktion, die von der Maschine mit Typ

IO ([Char]→ [Char]) produziert wir, anzuwenden.

• Warum gibt es keine Funktion :: IO α→ α ?

Losung Tatsachlich ist IO auch Instanz von Applicative:

1 Prelude> pure (++) <*> readFile "foo.txt" <*> readFile "bar.txt"

2 "Hello outside world!\nThis is from a file\n"

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 495

Page 496: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Gesetze fur Applicative · 14.6

14.6 Gesetze fur Applicative

Damit die Intuition funktioniert, muss Folgendes gelten:

1. pure id~ v ≡ v Vertraglichkeit mit der Identitat• Wenn man die Identitat in einen Kontext hebt, und sie dann auf einen Wert

im Kontext anwendet, darf sich dieser nicht andern.

2. pure g ~ pure x ≡ pure (g x) Homomorphismus61

• Eine Berechnung “im Kontext” muss sich genau so verhalten wie dieBerechnung außerhalb, deren Ergebnis man in den Kontext hebt.

3. u ~ pure y ≡ pure ($ y)~ u Austauschbarkeit• Bei Anwendung einer “Berechnung mit Effekt” u auf ein reines Argument y

spielt keine Rolle in welcher Reihenfolge u und y ausgewertet werden.

4. u ~ (v ~ w) ≡ pure (◦)~ u ~ v ~ w Komposition• Auch Komposition vertragt sich mit Lifting: Vergleiche: a (b c) ≡ (◦) a b c .

5. fmap g u ≡ pure g ~ u Das Verhaltnis zu Functor• Die ersten vier Gesetze implizieren dieses (ohne Beweis).

61Vertraglichkeit mit der AnwendungStefan Klinger · DBIS Informatik 2 · Sommer 2016 496

Page 497: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Gesetze fur Applicative · 14.6

AnmerkungenI Man kann fmap in zwei primitivere Operationen zerlegen: Lifting, und

Anwendung innerhalb des Kontexts.• Die Gleichung fmap g u ≡ pure g ~ u kann man also auch als Definition

von fmap durch pure und ~ lesen.

• Tatsachlich ist lassen sich beide Functor-Gesetze aus denApplicative-Gesetzen beweisen.

⇒ Hat man schon eine valide Instanziierung zu Applicative, dann geht auch:

1 instance Functor Maybe where fmap g u = pure g <*> u

2 instance Functor (Either t) where fmap g u = pure g <*> u

3 instance Functor [] where fmap g u = pure g <*> u

4 instance Functor ((->) t) where fmap g u = pure g <*> u

I Oft gibt es zu einer Implementation von ~ nur eine Implementationvon pure welche die genannten Gesetze erfullt.• Zwar gibt es oft mehrere Moglichkeiten einen Functor Applicative zu

machen (Comprehension, cf. Seite 485 und ZipList, cf. Seite 486).

• Aber fur diese beiden Instanziierungen von Listen zu Applicative hatten wirjeweils keine andere Wahl fur pure.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 497

Page 498: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Gesetze fur Applicative · 14.6

Kanonische Form

Ubung Die drei Gesetze

I pure g ~ pure x ≡ pure (g x) Homomorphismus

I u ~ pure y ≡ pure ($ y)~ u Austauschbarkeit

I u ~ (v ~ w) ≡ pure (◦)~ u ~ v ~ w Komposition

beschreiben einen Algorithmus, wie man jeden Ausdruck mit pure und ~so umschreiben kann, dass er die kanonische Form

pure g ~ u1 ~ u2 ~ ...~ un

hat, in der pure nur einmal vorkommt, und die ~ linkstief geschachtelt sind.(Erinnerung: ~ ist links-assiziativ)

Intuition Berechnungen mit Effekt haben eine “reine” (pure) Struktur diedurch g gegeben ist, plus eine Reihe von “effektbehafteten”Unter-Berechnungen in den ui .

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 498

Page 499: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Gesetze fur Applicative · 14.6

Notation Weil fmap g u ≡ pure g ~ u gilt (cf. Seite 496, 5. Gesetz),definiert man noch

1 infixl 4 <$>

2 (<$>) :: Functor f => (a -> b) -> f a -> f b

3 (<$>) = fmap

Damit konnen applikative Berechnung immer in die Form

g 〈$〉 u1 ~ u2 ~ ...~ un

gebracht werden. Dabei sind

I die ui :: f αi (fur den gleichen Functor f ), undI g :: α1 → α2 → ...→ αn → β.I Der ganze Ausdruck ist vom Typ f β.

Prima! Offenbar konnen wir mehrere IO-Operationen an ein reinfunktionales Programm “anflanschen”. Nochmal das Beispiel von Folie 483:

1 Prelude> (++) <$> readFile "foo.txt" <*> readFile "bar.txt"

2 "Hello outside world!\nThis is from a file\n"

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 499

Page 500: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Gesetze fur Applicative · 14.6

nicht-applikative Funktoren

I Jede Instanz von Applicative bildet notwendigerweise einen Functor,fmap g u ≡ pure g ~ u (cf. Seite 497).

I Umgekehrt gilt das nicht!

Das bedeutet: Es gibt Funktoren die sich nicht ohne weiteres62 applikativverwenden lassen!

Beispiel Erinnerung: ((,) τ) ist ein Functor:

1 instance Functor ((,) τ) where

2 fmap f (x,y) = (x, f y) — fmap :: (α→ β)→ (τ , α)→ (τ , β)

I Brauchen: pure :: α→ (τ, α).I Aber woher soll man den Wert fur τ nehmen?

• Ein Ansatz ware pure x = (⊥, x), aber das kollidiert mit den Gesetzen die furApplicative gelten sollen, cf. Seite 496 (auch eine schone Ubung).

62“Weiteres” nachste Woche im PK2.Stefan Klinger · DBIS Informatik 2 · Sommer 2016 500

Page 501: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Gesetze fur Applicative · 14.6

Applicative ohne Container

Erinnerung

1 instance Functor ((→) τ) where

2 fmap = (.)

Der “Kontext” ist hier etwas das einenWert vom Typ τ = [α] bereitstellt.

3 *Main> :t length

4 length :: [α] → Int

5 *Main> :t (<3)

6 (<3) :: Int → Bool

7 *Main> :t fmap (<3) length

8 fmap (<3) length :: [α] → Bool

Was brauchen wir fur eine Instanziierung Applicative ((→) τ) ?

1. Was sind die benotigten Typen von pure und ~?

2. Wie konnen wir die implementieren? (Tip: “let the types guide you”)

3. Gelten die Gesetze, cf. Seite 496?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 501

Page 502: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Gesetze fur Applicative · 14.6

Das sind alte Bekannte: Die Schonfinkel-Kombinatoren63

1 instance Functor ((→) τ) where — nur zur Erinnerung nochmal2 fmap = (.)

3

4 instance Applicative ((→) τ) where

5 —pure :: α→ (τ → α)6 pure = const —K = λx y . x7 — (~) :: (τ → α→ β)→ (τ → α)→ τ → β8 f <*> g = \x -> f x (g x) — S = λf g x . f x (g x)9

10

11 *Main> :t (&&) <$> even — Funktion im Functor (Int→)12 (&&) <$> even :: Int → Bool → Bool

13

14 *Main> :t (<3) —Bool-Wert im Functor (Int→)15 (<3) :: Int → Bool

16

17 *Main> :t (&&) <$> even <*> (<3) — Anwendung der Funktion auf den Wert.18 (&&) <$> even <*> (<3) :: Int → Bool

Der Beweis der Gesetze von Folie 484 ist einfache Rechnerei (gute Ubung).

63https://svn.uni-konstanz.de/dbis/inf2_16s/pub/pk2-12.lhsStefan Klinger · DBIS Informatik 2 · Sommer 2016 502

Page 503: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Gesetze fur Applicative · 14.6

Ist Applicative schon genug?

Aufgabe Schreibe eine Funktion list, die einen Dateinamen von stdin

liest, und den Inhalt dieser Datei zuruckgibt.

I Bekannt sind:

Bekannt: getLine :: IO StringreadFile :: String→ IO String

Gesucht: list :: IO String

• Dabei soll das Ergebnis von getLine als Eingabe von readFile dienen,• das Ergebnis von readFile mochten wir zuruck bekommen.

I Wie konnen wir getLine und readFile verknupfen?

1 Prelude> :t readFile <*> getLine — Was kommt hier raus?2 Prelude> :t readFile <$> getLine — Was kommt hier raus?

Erinnerung: (~) :: f (α→ β)→ f α→ f β, und fmap :: (α→ β)→ f α→ f β.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 503

Page 504: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Gesetze fur Applicative · 14.6

I Wir konnen IO-Operationen an ein rein funktionales Program“anschließen” (cf. Seite 499), aber diese Operationen konnen nichtmiteinander kommunizieren!

(~) :: f (α→ β)→ f α→ f β

• Die beiden Argumente von ~ stehen fur separate “Maschinen”, oder“Berechnungen mit Effekt”,

• die erste :: f (α→ β) produziert eine Funktion,• die zweite :: f α produziert ein Argument,• ~ konstruiert die Maschine, welche die Funktion auf das Argument anwendet,

und das Ergebnis zuruckgibt.

I Wir brauchen etwas anderes:

f α→ (α→ f β)→ f β

Das zweite Argument :: (α→ f β) soll entscheiden konnen welcheIO-Operation ausgefuhrt wird.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 504

Page 505: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Monad · 14.7

14.7 Monad (dt. Monade)

1 class Applicative m ⇒ Monad m where

2

3 (>>=) :: m α → (α → m β) → m β — dieser Operator heißt Bind4

5 (>>) :: m α → m β → m β6 u >> v = u >>= const v

7

8 return :: α → m α9 return = pure — Aus historischen Grunden hier nochmal mit neuem Namen

Beobachtungen Monad ist also ein besonderer applikativer Funktor.

I Das einzig interessante ist der Bind-Operator >>=.I Erst spater kummern wir uns um:

• >> (aka. then) ist eine spezielle Version von >>=.• return ist einfach ein neuer Name fur pure, der aus historischen Grunden

hier auftaucht, besser ware wohl man hatte Monad ohne return.

⇒ Konzentrieren wir uns also auf >>=.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 505

Page 506: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Monad · 14.7

Lernen aus dem Typ von >>=

m ist ein Typ vom Kind ∗ → ∗, also ein Typkonstruktor mit einemArgument.

>>= :: Monad m ⇒ m α→ (α→ m β)→ m β

I Wurde man Maybe fur m einsetzen, hatte man:

>>= :: Maybe α→ (α→ Maybe β)→ Maybe β

I Wurde man Either τ fur m einsetzen, hatte man:

>>= :: Either τ α→ (α→ Either τ β)→ Either τ β

I Wurde man [ ] fur m einsetzen, hatte man:

>>= :: [α]→ (α→ [β])→ [β]

I Wurde man (τ →) fur m einsetzen, hatte man:

>>= :: (τ → α)→ (α→ (τ → β))→ (τ → β)

Frage Wie konnte man die konstruieren?Stefan Klinger · DBIS Informatik 2 · Sommer 2016 506

Page 507: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Monad · 14.7

I Wenn man den Typen folgt, kommt man auf diese Implementierungen:

1 instance Monad Maybe where

2 Just x >>= g = g x

3 Nothing >>= _ = Nothing

4

5 instance Monad (Either t) where

6 Right x >>= g = g x

7 Left l >>= _ = Left l

8

9 instance Monad ((->) t) where

10 h >>= g = \x -> g (h x) x

11

12 instance Monad [] where

13 xs >>= g = concatMap g xs

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 507

Page 508: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Monad · 14.7

Gesetze fur Monad

I Wenn man sich m α als “Berechnung” vorstellt, die einen Wert vom Typα liefert, dann ubergibt >>= dieses Ergebnis an eine Funktion vom Typα→ m β:

>>= :: Monad m ⇒ m α→ (α→ m β)→ m β

Gesetze Das muss gelten:

1. return x >>= v ≡ v x• Die Berechnung die x liefert an v gebunden, ist das Gleiche wie v auf x

anwenden.

2. m >>= return ≡ m• Das Ergebnis einer Berechnung an return ubergeben liefert die gleiche

Berechnung mit dem gleichen Ergebnis.

3. (m >>= k) >>= h ≡ m >>=(λx . k x >>= h)• Das dritte Gesetz beschreibt eine Art Assoziativitat fur >>=.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 508

Page 509: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen Monad · 14.7

Monaden sind immer applikative Funktoren

Jeder Monad ist notwendigerweise auch Applicative (und damit auchgleich noch Functor, cf. Seite 497).

Beweisidee Es genugt pure und ~ durch return und >>= zu definieren,und die Gesetze fur Applicative aus den Gesetzen von Monad herzuleiten.

I pure = return

I g ~ v = g >>=(λh. v >>=(λx . return (h x)))• g :: m (α→ β) enthalt eine Funktion, der linke Bind-Operator packt diese

aus, und bindet sie an h :: α→ β.• Ebenso gelangen wir an das Argument x :: α das in v :: m α steckt.• Das Ergebnis von h x :: β wird mit return zuruckgegeben. Das ist notig, weil

das zweite Argument von >>= einen monadischen Typ haben muss, also m β.

I Das Beweisen der Gesetze ist Rechnerei, aber nicht arg schwierig.

Obacht Nicht jeder applikative Functor lasst sich als Monad auffassen:Die ZipList-Instanziierung von Listen zu Applicative (cf. Seite 486) lasstsich nicht zu Monad erweitern!

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 509

Page 510: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen monadic IO · 14.8

14.8 monadic IO Ein-/Ausgabe mit Monaden

Wenn man sich unser Interface zu Strukturen, oder “effektbehaftetenBerechnungen” anschaut, sollte etwas auffallen:

fmap :: Functor f ⇒ (α→ β)→ (f α→ f β)

pure :: Applicative f ⇒ α→ f α(~) :: Applicative f ⇒ f (α→ β)→ (f α→ f β)

return :: Monad m ⇒ α→ m α(>>=) :: Monad m ⇒ m α→ (α→ m β)→ m β

Was?

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 510

Page 511: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen monadic IO · 14.8

~

Wichtig Die “Richtung” ist immer vorgegeben: Alle Funktionenfuhren in die Struktur, oder operieren darin.

I Es gibt keine Funktion die den “Kontext” verlasst, etwa

escape :: Functor f ⇒ f α→ α

I Fur spezielle Strukturen kennen wir solche Funktionen zwar, z.B.

maybe :: β → (α→ β)→ Maybe α→ β

aber die Existenz einer solchen Funktion wird von keiner der KlassenFunctor, Applicative oder Monad gefordert.

Konsequenz Was in der Struktur passiert bleibt in der Struktur.Und das eignet sich hervorragend fur IO: Alle Seiteneffekte sind in derIO-Struktur gefangen, sie konnen unsere rein funktionale Welt nichtverschmutzen, oder die Referenzielle Transparenz zerstoren.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 511

Page 512: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen monadic IO · 14.8

Die IO-Monade

I IO ist tatsachlich Instanz von Monad:1 Prelude> :i IO

2 — ...3 instance Monad IO — Defined in ‘GHC.Base’4 instance Functor IO — Defined in ‘GHC.Base’5 instance Applicative IO — Defined in ‘GHC.Base’

I Damit konnen wir die Aufgabe von Folie 491 losen:

1 list = getLine >>= readFile

2

3 Prelude> :t list

4 list :: IO String

5

6 Prelude> list

7 foo.txt — meine Eingabe8 "hello outside world\n" — das Ergebnis der Berechnung

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 512

Page 513: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen monadic IO · 14.8

Monadische Operationen zusammensetzen

Als Instanz von Monad konnen wir das Ergebnis einer IO-Berechnungverwenden, um eine neue IO-Berechnung zu erzeugen:

Beispiel

1 Prelude> getLine >>= putStrLn — cf. Seite 4932 flotsch

3 flotsch

4

5 Prelude> getLine >>= \_ -> putStrLn "foo"

6 lala

7 foo

8

9 Prelude> putStrLn "Name:" >>= (\_-> getLine >>= (\x -> putStrLn ("Hello " ++ x)))

10 Name:

11 Joe

12 Hello Joe

13

14 Prelude> length <$> readFile "foo.txt" >>= \n-> putStrLn (show n ++ " Zeichen")

15 13 Zeichen

Die hervorgehobene Ausgabe ist nicht das Ergebnis der IO-Operation (das ist hier immer()), sondern die Ausgabe welche von der IO-Operation als Seiteneffekt erzeugt wurde.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 513

Page 514: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen monadic IO · 14.8

do-Notation

Das ist nicht lesbar:

1 foo'''2 = putStrLn "Name:" >>= \_-> getLine >>= \name-> putStrLn "Age:" >>= \_->

3 stringToInt <$> getLine >>= \age-> let verdict = if (age < 42) then

4 "young" else "old" in putStrLn $ name++" is "++verdict

I Haufig braucht man eine IO-Operation wegen ihrem Seiteneffekt, und istan dem Ergebnis der Berechnung nicht interessiert:

1 Prelude> putStrLn "Gimme text:" >>= \_-> length <$> getLine

2 Gimme text:

3 hello

4 5

I Dafur ist eine spezielle Variante von >>= vorgesehen:

1 u >> v = u >>= const v

2

3 Prelude> putStrLn "Gimme text:" >> length <$> getLine

4 Gimme text: dabadidabadu

5 12

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 514

Page 515: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen monadic IO · 14.8

Mit >> wird der code minimal lesbarer:1 foo''2 = putStrLn "Name:" >> getLine >>= \name-> putStrLn "Age:" >> stringToInt

3 <$> getLine >>= \age-> let verdict = if (age < 42) then "young" else "old"

4 in putStrLn $ name++" is "++verdict

Wenn man die Zeilenumbruche nicht vollig willkurlich setzt...

1 foo' = putStrLn "Name:" >>

2 getLine >>= \name-> — Zuweisung name := getLine ?3 putStrLn "Age:" >>

4 stringToInt <$> getLine >>= \age-> — age := stringToInt <$> getLine ?5 let verdict = if (age < 42)

6 then "young"

7 else "old"

8 in putStrLn $ name++" is "++verdict

...sieht’s aus wie ein imperatives Programm!

I u >>=λx . v Bindet das Ergebnis der Berechnung u an die Variable x ,welche dann in v verwendet werden kann.

I u >> v Fuhrt erst u aus, und dann v . Das Ergebnis von u wird ignoriert.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 515

Page 516: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen monadic IO · 14.8

Syntaktischer Zucker

I Haskell verstarkt diesen Eindruck mit einer speziellen syntaktischenForm: do-Notation.

I Ein Ausdruckdo { c1 ; ... ; cn }

fuhrt die monadischen Berechnungen c1, ..., cn nacheinander aus.

I Eine Berechnung ci (mit i < n) ist dabei entweder• ein Ausdruck ei :: m αi ,• eine Variablenbindung pi <- ei mit einem Ausdruck ei :: m αi und einem

Pattern pi :: αi , oder• eine let-Klausel (nachste Seite).

I Die letzte Berechnung cn ist immer ein Ausdruck en :: m αn, undbestimmt den Ruckgabewert des do-Blocks.

Wichtig Die monadischen Berechnungen e1, ..., en operieren auf dergleichen Monade m, konnen aber verschiedene Ruckgabetypenα1, ..., αn haben.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 516

Page 517: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen monadic IO · 14.8

Operationale Semantik

Ahnlich zur List-Comprehension (cf. Seite 247) werden do-Ausdrucke aufden Sprachkern abgebildet.

Definition Semantik der do-Notation

Seien e :: m α, p ein Pattern, und decls Deklarationen wie beilet-Ausdrucken. Sei es eine nicht-leere Sequenz von Haskell-Ausdrucken.

do { e } → e

do { e ; es } → e >> do { es }do { p <- e ; es } → e >>= \x -> case x of

p -> do { es }_ -> fail "ERROR"

do { let decls ; es } → let decls in do { es }

I "ERROR" wird vom Compiler erzeugt und sollte uber die Position inQuellcode informieren.

I Der letzte Ausdruck in es darf nicht die Formen p <- e oderlet decls haben.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 517

Page 518: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen monadic IO · 14.8

Damit ist das Programm schon lesbar:

1 foo = do putStrLn "Name:"

2 name <- getLine

3 putStrLn "Age:"

4 age <- stringToInt <$> getLine

5 let verdict = if (age < 42)

6 then "young"

7 else "old"

8 putStrLn $ name++" is "++verdict

9

10 *Main> :t foo

11 foo :: IO ()

12 *Main> foo

13 Name:

14 Agecanonix

15 Age:

16 93

17 Agecanonix is old

I Wie auch bei let-Ausdrucken wird zweidimensionale Syntax unterstutzt,d.h. die geschweiften Klammern und Semikola sind durch die Einruckungimplizit gegeben.

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 518

Page 519: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen monadic IO · 14.8

Programme kompilieren

I Schreiben eine Datei filesize.lhs mit dem Inhalt:

1 > module Main where

2

3 Kompilierbare Programme mussen ein Modul Main,4 und darin eine Funktion main :: IO() haben.5

6 > main :: IO ()

7 > main = do putStrLn "Enter file name:"

8 > p <- getLine

9 > s <- length <$> readFile p

10 > putStrLn $ p++" has size "++show s

I ...Kompilieren und testen:

1 $ ghc filesize.lhs

2 [1 of 1] Compiling Main ( filesize.lhs, /.../Main.o )

3 Linking filesize ...

4 $ ./filesize

5 Enter file name:

6 filesize.lhs

7 filesize.lhs has size 174

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 519

Page 520: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen monadic IO · 14.8

Monad-Laws und do-Notation

Hier nochmal der Zusammenhang zwischen den Monaden-Gesetzen und derdo-Notation:

1. p >>= return ≡ p

do{ x ← p; return x }≡

do{ p }

2. return e >>= q ≡ q e

do{ x ← return e; es }≡

do{ es[x�e] }

3. (p >>= q) >>= r ≡ p >>=(λx . q x >>= r)

do{ x ← do{ es; q }; r x}≡

do{ es; x ← q; r x }

Ohne die Gultigkeit der Monaden-Gesetze konnte man die do-Ausdruckenicht so umformen!

Stefan Klinger · DBIS Informatik 2 · Sommer 2016 520

Page 521: Informatik 2 - Konzepte der Programmierung [2 ...Informatik 2 Konzepte der Programmierung (& Programmierkurs 2) Stefan Klinger LS Scholl, Datenbanken und Informationssysteme Universit

14 · Monadische Berechnungen monadic IO · 14.8

Literatur

I Conor McBride, Ross Paterson. Applicative Programming with Effects. InJournal of Functional Programming 18:1 (2008), pages 1-13.http://www.soi.city.ac.uk/~ross/papers/Applicative.pdf

I Brent Yorgey. Typeclassopedia.https://wiki.haskell.org/Typeclassopedia.

Eine andere Anwendung (ohne IO) fur monadische Berechnungen istParsec64, eine Bibliothek von Kombinatoren zur Konstruktion von Parsern.Leider ist die Dokumentation gerade etwas unzuganglich.

64http://hackage.haskell.org/package/parsecStefan Klinger · DBIS Informatik 2 · Sommer 2016 521