Universität Bielefeld Programmieren in Haskell Giegerich Programmieren in Haskell WS 2012/2013 Prüfungsvorbere Imperative Programmierung IO Monaden Robert Giegerich Universität Bielefeld AG Praktische Informatik 15. Januar 2014 Prüfungen ... Wissenschaftlich sinnvolle Prüfung wäre folgendes Universität Bielefeld Programmieren in Haskell sich vergewissern wieviel man verstanden hat; Feedback etc ... Prüfungsvorbere möglichst alle Wissenslücken entdecken, weil man sie noch schließen will Imperative Programmierung weiß man schon genug, um aufbauendes Wissen effektiv zu lernen? Giegerich IO Monaden Prüfungen ... Wissenschaftlich sinnvolle Prüfung wäre folgendes Universität Bielefeld Programmieren in Haskell sich vergewissern wieviel man verstanden hat; Feedback etc ... Prüfungsvorbere möglichst alle Wissenslücken entdecken, weil man sie noch schließen will Imperative Programmierung weiß man schon genug, um aufbauendes Wissen effektiv zu lernen? Wissenschaftlich unsinnige Prüfungen sehen so aus: Noten Prüfung als Ausschluss von (weiterem) Wissen Prüfung als Leistung pro Zeit Lernen als Wettrennen Giegerich IO Monaden Prüfungen ... Wissenschaftlich sinnvolle Prüfung wäre folgendes Universität Bielefeld Programmieren in Haskell sich vergewissern wieviel man verstanden hat; Feedback etc ... Prüfungsvorbere möglichst alle Wissenslücken entdecken, weil man sie noch schließen will Imperative Programmierung weiß man schon genug, um aufbauendes Wissen effektiv zu lernen? Wissenschaftlich unsinnige Prüfungen sehen so aus: Noten Prüfung als Ausschluss von (weiterem) Wissen Prüfung als Leistung pro Zeit Lernen als Wettrennen Dies dient, ganz allgemein, der Organisation der Ausbildung als Konkurrenz um Berufschancen Giegerich IO Monaden Kontraproduktive Wirkungen der Lernkonkurrenz Universität Bielefeld Programmieren in Haskell Giegerich Die Form der Konkurrenz behindert den Wissenserwerb: Angst, Fragen zu stellen Prüfungsvorbere Abtreten des eigenen Urteils an die Abstraktion Note Imperative Programmierung statt eigener Motivation Abarbeiten eines Anforderungskatalogs IO eigenes Interesse definiert durch Prüfungsrelevanz Übergänge in die Psychologie: Angeber, Selbstzweifler, Prüfungsangst Das ist kein Mißstand, sondern ... Monaden Kontraproduktive Wirkungen der Lernkonkurrenz Universität Bielefeld Programmieren in Haskell Giegerich Die Form der Konkurrenz behindert den Wissenserwerb: Angst, Fragen zu stellen Prüfungsvorbere Abtreten des eigenen Urteils an die Abstraktion Note Imperative Programmierung statt eigener Motivation Abarbeiten eines Anforderungskatalogs IO eigenes Interesse definiert durch Prüfungsrelevanz Übergänge in die Psychologie: Angeber, Selbstzweifler, Prüfungsangst Das ist kein Mißstand, sondern ... ... ein gesellschaftlicher Auftrag: Charakterbildung für die Konkurrenz im Berufsleben Monaden Prüfungstipps von Georg Sauthoff (WS 2011/12) Welche Veranstaltungen werden geprüft? A&D Vorlesung Programmieren in Haskell A&D Übung Programmieren in der UNIX-Umgebung Wer prüft? Prüfer Beisitzer Wie lange? 20 Minuten Wann? siehe Termine Was muss mitgebracht werden? Personalausweis bzw. Pass Studentenausweis Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Prüfungsziel Universität Bielefeld Programmieren in Haskell Giegerich Test inwieweit Veranstaltungsinhalte verstanden werden und angewendet werden können. Prüfungsvorbere Imperative Programmierung IO Monaden Prüfungsziel Universität Bielefeld Programmieren in Haskell Giegerich Test inwieweit Veranstaltungsinhalte verstanden werden und angewendet werden können. Verschiedene Arten von Leistungen Prüfungsvorbere Imperative Programmierung IO Reproduktion Transfer (konkret) Transfer (abstrakt) Monaden Prüfungsziel Universität Bielefeld Programmieren in Haskell Giegerich Test inwieweit Veranstaltungsinhalte verstanden werden und angewendet werden können. Verschiedene Arten von Leistungen Prüfungsvorbere Imperative Programmierung IO Reproduktion Transfer (konkret) Transfer (abstrakt) Prüfen auf eine möglichst gute Note hin. Monaden Vorbereitung Universität Bielefeld Programmieren in Haskell Giegerich Materialien Vorlesungsfolien Übungsunterlagen Skript Prüfungsprotokolle, dabei jeweils beachten: Motivation Hintergrund Übungsgruppen Sprechstunden Prüfungsvorbere Imperative Programmierung IO Monaden Ablauf Universität Bielefeld Programmieren in Haskell Giegerich Prüfer stellt die Fragen Beisitzer protokolliert hauptsächlich Ausweiskontrolle Einstiegsfrage Prüfungsvorbere Imperative Programmierung IO Monaden nach ∼ 20 Minuten: Ende Student geht vor die Tür Prüfer und Beisitzer beraten sich kurz Student wird wieder hereingebeten Mitteilung der Note und Feedback 10 einfache Regeln zum Versemmeln einer Prüfung 1 erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung beginnen Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden 10 einfache Regeln zum Versemmeln einer Prüfung 1 2 erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung beginnen alleine Lernen, obwohl das eigentlich noch nie gut geklappt hat Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden 10 einfache Regeln zum Versemmeln einer Prüfung 1 2 3 erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung beginnen alleine Lernen, obwohl das eigentlich noch nie gut geklappt hat bei der Vorbereitung das Skript ignorieren Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden 10 einfache Regeln zum Versemmeln einer Prüfung 1 2 3 4 erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung beginnen alleine Lernen, obwohl das eigentlich noch nie gut geklappt hat bei der Vorbereitung das Skript ignorieren Verzicht auf eine aktiven Bearbeitung der Übungen Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden 10 einfache Regeln zum Versemmeln einer Prüfung 1 2 3 4 5 erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung beginnen alleine Lernen, obwohl das eigentlich noch nie gut geklappt hat bei der Vorbereitung das Skript ignorieren Verzicht auf eine aktiven Bearbeitung der Übungen strikt vermeiden ein Haskell-Programm selbst zu schreiben Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden 10 einfache Regeln zum Versemmeln einer Prüfung 1 2 3 4 5 6 erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung beginnen alleine Lernen, obwohl das eigentlich noch nie gut geklappt hat bei der Vorbereitung das Skript ignorieren Verzicht auf eine aktiven Bearbeitung der Übungen strikt vermeiden ein Haskell-Programm selbst zu schreiben Inhalte auswendig lernen Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden 10 einfache Regeln zum Versemmeln einer Prüfung 1 2 3 4 5 6 7 erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung beginnen alleine Lernen, obwohl das eigentlich noch nie gut geklappt hat bei der Vorbereitung das Skript ignorieren Verzicht auf eine aktiven Bearbeitung der Übungen strikt vermeiden ein Haskell-Programm selbst zu schreiben Inhalte auswendig lernen möglichst unausgeschlafen in die Prüfung kommen Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden 10 einfache Regeln zum Versemmeln einer Prüfung 1 2 3 4 5 6 7 8 erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung beginnen alleine Lernen, obwohl das eigentlich noch nie gut geklappt hat bei der Vorbereitung das Skript ignorieren Verzicht auf eine aktiven Bearbeitung der Übungen strikt vermeiden ein Haskell-Programm selbst zu schreiben Inhalte auswendig lernen möglichst unausgeschlafen in die Prüfung kommen auf die Frage nach Unklarheiten vor dem Beginn der Prüfung, am besten sehr lang und breit erklären, wie schlecht vorbereitet man doch ist Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden 10 einfache Regeln zum Versemmeln einer Prüfung 1 2 3 4 5 6 7 8 9 erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung beginnen alleine Lernen, obwohl das eigentlich noch nie gut geklappt hat bei der Vorbereitung das Skript ignorieren Verzicht auf eine aktiven Bearbeitung der Übungen strikt vermeiden ein Haskell-Programm selbst zu schreiben Inhalte auswendig lernen möglichst unausgeschlafen in die Prüfung kommen auf die Frage nach Unklarheiten vor dem Beginn der Prüfung, am besten sehr lang und breit erklären, wie schlecht vorbereitet man doch ist kommunizieren, dass man die Begriffe in den Veranstaltungstiteln nicht erklären kann Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden 10 einfache Regeln zum Versemmeln einer Prüfung 1 2 3 4 5 6 7 8 9 10 erst 3 Tage vor dem Prüfungstermin mit der Vorbereitung beginnen alleine Lernen, obwohl das eigentlich noch nie gut geklappt hat bei der Vorbereitung das Skript ignorieren Verzicht auf eine aktiven Bearbeitung der Übungen strikt vermeiden ein Haskell-Programm selbst zu schreiben Inhalte auswendig lernen möglichst unausgeschlafen in die Prüfung kommen auf die Frage nach Unklarheiten vor dem Beginn der Prüfung, am besten sehr lang und breit erklären, wie schlecht vorbereitet man doch ist kommunizieren, dass man die Begriffe in den Veranstaltungstiteln nicht erklären kann trotz Krankheit zur Prüfung erscheinen Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Weitere Angebote Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere ZSB bietet Workshops an eher allgemeine Hinweise vieles ist wahrscheinlich schon bekannt eher sinnvoll bei extremer Prüfungsangst o.Ä. Imperative Programmierung IO Monaden Fragestunde Universität Bielefeld Programmieren in Haskell Giegerich Die letzte Sitzung ist gedacht für Fragen, die aus der Vorbereitung resultieren, und kann diese nicht ersetzen! Wir teilen die Fragen in Themen ein – nach Kap. 1 - 6 A&D; nach Sprachkonzepten bei Haskell Macht euch vorher klar, was genau ihr fragen wollt, worin das Problem eigentlich besteht, in welche Kategorie es gehört. Dadurch wird manchmal schon etwas klar ... Bedenkt: Zu jeder gut gestellten Frage gibt es noch 5 andere Studis, die am gleichen Problem nagen. Die Sitzung wird nur so gut wie eure Fragen ... Prüfungsvorbere Imperative Programmierung IO Monaden Imperative Programmierung in Haskell Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung 1. Input und Output 2. Monaden Allgemeines IO Monaden Was heißt “imperativ?” Universität Bielefeld Programmieren in Haskell Giegerich Ein imperatives Programm besteht aus Anweisungen. Sie modifizieren einen globalen Zustand (Speicherzellen, Variablen, Drucker, Datei, ), ... ... und hängen auch von ihm ab. imp. Funktionen sind oft keine Funktionen im mathematischen Sinn, Wert von f (x ) hängt nicht nur von x , sondern auch vom gerade vorliegenden Zustand ab, d.h. das Prinzip der “referential transparency” ist verletzt. Die Ausführungsreihenfolge ist wesentlich und im Detail festgelegt. Beispiel: URM-Programme, C, Pascal, Java, ... Prüfungsvorbere Imperative Programmierung Allgemeines IO Monaden Referential Transparency (Wiederholung) ein Funktionsaufruf hat keine Seiteneffekte bei gleichen Argumentwerten bleibt der Funktionswert gleich wesentliches Merkmal von (puren) funktionalen Programmiersprachen ⇒ Vorteile bei der Analyse (Korrektheit, Effizienz, . . . ) und Optimierung von Code Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung Allgemeines IO Monaden Referential Transparency (Wiederholung) ein Funktionsaufruf hat keine Seiteneffekte bei gleichen Argumentwerten bleibt der Funktionswert gleich wesentliches Merkmal von (puren) funktionalen Programmiersprachen ⇒ Vorteile bei der Analyse (Korrektheit, Effizienz, . . . ) und Optimierung von Code Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung Allgemeines IO Monaden Beispiel für eine C-Funktion mit Seiteneffekten 1 int a = 0; 2 3 4 5 6 7 int f ( int x ) { a = a + 1; return x * x * a ; } Funktionale Programmierung im Unterschied zur imperativen Universität Bielefeld Programmieren in Haskell Giegerich Funktionale Sprache: Es werden nur Datenabhängigkeiten beschrieben, diese sind explizit (”referential transparency”), eine Berechnungsreihenfolge ist nicht festgelegt. Prüfungsvorbere Imperative Programmierung Allgemeines IO Monaden Es gibt keine Anweisungen, keinen Zustand, kein vorher/nachher Kann man eine zustandsbasierte Rechnung simulieren, wenn man sie unbedingt braucht? Expliziter Zustand Universität Bielefeld Programmieren in Haskell Giegerich 1 2 3 Simulation der zustandsbasierten Rechnung: Expliziten Zustand s einführen. Statt z = f x y; r = g z nun überall Zustand angeben, z.B. (s ’ , z ) = f s x y (s ’ ’ , u ) = f s ’ x y (s ’ ’ ’ , r ) = g s ’ ’ z und ein Zustand s darf nie zweimal benutzt werden. Jedoch: Im “normalen” Haskell gibt es aber keine Hindernis, alle drei gleichzeitig zu benutzen Prüfungsvorbere Imperative Programmierung Allgemeines IO Monaden Erwünschte Zustände Universität Bielefeld Programmieren in Haskell Giegerich Wo wünscht man sich die imperative Programmierung: Ein-und Ausgabe sind inhärent zustandsabhängig und müssen in ihrer Abfolge koordiniert werden Funktionen mit “Nebenergebnis”, das überall behandelt werden muss, möchten dies in einem “Zustand” verstecken. Beispiel: Rechnen mit dem Typ Maybe Int Dafür gibt es in Haskell ein besonderes Konzept – Monaden – und eine spezielle Notation – do-Notation . Prüfungsvorbere Imperative Programmierung Allgemeines IO Monaden IO in Haskell – wie es nicht geht Universität Bielefeld Programmieren in Haskell Giegerich 1 2 Erster Ansatz wäre vielleicht: r e a d C h a rFromKeybo a r d :: Char r e ad I n tFromKeyboa r d :: Int 3 4 Prüfungsvorbere Imperative Programmierung IO stringToScreen :: String -> Bool Monaden IO in Haskell – wie es nicht geht Universität Bielefeld Programmieren in Haskell Giegerich 1 2 Erster Ansatz wäre vielleicht: r e a d C h a rFromKeybo a r d :: Char r e ad I n tFromKeyboa r d :: Int 3 4 Prüfungsvorbere Imperative Programmierung IO stringToScreen :: String -> Bool Probleme dabei Auswertungsreihenfolge Verletzung der Referential Transparency von Funktionen Monaden Auswertungsreihenfolge Universität Bielefeld Programmieren in Haskell Giegerich besonders bei Lazy-Evaluation Prüfungsvorbere Imperative Programmierung IO Monaden Auswertungsreihenfolge Universität Bielefeld Programmieren in Haskell Giegerich besonders bei Lazy-Evaluation Prüfungsvorbere Example f x = x + readInt Fr o m Ke y b oa r d - readInt F r om K e yb o a rd Imperative Programmierung IO Monaden Auswertungsreihenfolge Universität Bielefeld Programmieren in Haskell Giegerich besonders bei Lazy-Evaluation Prüfungsvorbere Example f x = x + readInt Fr o m Ke y b oa r d - readInt F r om K e yb o a rd printList [] = ? printList ( x : xs ) = stringToScreen x ...?... printList xs main ... = ... printList l Imperative Programmierung IO Monaden do-Notation Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere do-Notation erlaubt Folge von Aktionen zu programmieren: Sie werden der Reihe nach ausgeführt können Werte berechnen und an Variable übergeben (aber nur einmal!) oder auch nur etwas ausführen Werte aus zuvor berechneten Variablen benutzen Imperative Programmierung IO Monaden Abstrakter Datentyp IO Universität Bielefeld Programmieren in Haskell Giegerich Ein- und Ausgabefunktionen sind “Aktionen” eines abstrakten Datentyps IO a Prüfungsvorbere Imperative Programmierung werden importiert wie üblich: import IO IO Eingaben haben den Typ z.B. IO String oder IO Int Monaden Ausgabe-Aktionen liefern den Typ IO () Für die Verkettung von Aktionen gibt es eine besondere Notation Beispiel: do x <- getLine; print (length x) Verkettung von “Aktionen” Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere 1 > do 2 x <- act1 act2 y <- act3 x act4 x y return ( f x y ) Ausführung der Aktionen 1 - 4 in der angegebenen Reihefolge, Erzeugung und Wiederverwendung von Zwischenergebnissen 3 4 5 6 Imperative Programmierung IO Monaden IO-Beispiel: Ausgabe Universität Bielefeld Programmieren in Haskell Giegerich 1 putStr :: String -> IO () 2 3 putStrLn :: String -> IO () 4 5 6 1 2 3 4 -- vordefiniert Prüfungsvorbere Imperative Programmierung IO putStrLn str = do putStr str putStr ‘ ‘\n ’ ’ put4times str = do putStrLn str putStrLn str putStrLn str putStrLn str Monaden IO-Beispiel: Eingabe Universität Bielefeld Programmieren in Haskell Giegerich 1 2 3 4 5 6 7 8 getLine :: IO String getChar :: IO Char -- vordefiniert -- vordefiniert Prüfungsvorbere Imperative Programmierung IO read2lines :: IO () Monaden read2lines = do getLine getLine putStrLn " Two lines read and used for nothing " Die Zeilen werden zwar von der Eingabe entnommen, aber dann nicht weiter verwendet ... IO-Beispiel: Eingabeverarbeitung und Ausgabe Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere 1 2 3 4 5 reverse2lines :: IO () reverse2lines = do line1 <- getLine line2 <- getLine putStrLn ( reverse line2 ) putStrLn ( reverse line1 ) Die eingelesenen Strings werden an Namen gebunden und können so in anderen Funktionen verwendet werden Imperative Programmierung IO Monaden Weitere IO-Funktionen Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Weitere IO-Funktionen für Lesen und Schreiben von Dateien Kommunikation mit dem Betriebssystem ... Imperative Programmierung IO Monaden IO-Funktionen Universität Bielefeld Programmieren in Haskell 1 2 getChar getLine :: IO Char :: IO String putChar putStr putStrLn print :: :: :: :: 3 4 5 6 7 Char -> IO () String -> IO () String -> IO () Show a = > a -> IO () Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden IO-Funktionen Universität Bielefeld Programmieren in Haskell 1 2 getChar getLine :: IO Char :: IO String putChar putStr putStrLn print :: :: :: :: 3 4 5 6 7 Char -> IO () String -> IO () String -> IO () Show a = > a -> IO () Wiederholung () ist der Unit-Datentyp, der nur den Wert () enthält Die Typen der IO-Funktionen erklären, warum man sie in der do-Notation (s.o.) gebrauchen kann Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Main bei kompilierten Programmen per Standard wird bei einem kompilierten Programm die Funktion main in dem Module Main als Programmeinsprung verwendet: > module Main > where > main :: IO () Zugriff auf Kommandozeilenargumente: import System Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden getArgs :: IO [ String ] Exit-Status: data ExitCode = ExitSuccess | ExitFailure Int deriving ( Eq , Ord , Read , Show ) exitWith :: ExitCode -> IO a Main — btw Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Falls ein Modul keine module-Deklaration enthält, ist das äquivalent zu: Imperative Programmierung IO Monaden 1 2 > module Main ( main ) > where Convenience-IO-Funktionen Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere 1 2 3 readFile :: FilePath -> IO String writeFile :: FilePath -> String -> IO () appendFile :: FilePath -> String -> IO () Imperative Programmierung IO Monaden Convenience-IO-Funktionen Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere 1 2 3 readFile :: FilePath -> IO String writeFile :: FilePath -> String -> IO () appendFile :: FilePath -> String -> IO () Imperative Programmierung IO Monaden Sonstige IO-Funktionen: 1 2 openFile :: FilePath -> IOMode -> IO Handle ... Einfaches Beispiel Universität Bielefeld Programmieren in Haskell Giegerich 1 2 3 4 5 6 7 8 9 Datei lesen, verarbeiten, schreiben in Hugs > import IO Prüfungsvorbere Imperative Programmierung > encodeCube :: Int -> String -> String IO > decodeCube :: Int -> String -> String Monaden ... ... > encode file = do > inp <- readFile ( file ++ " . txt " ) > writeFile ( file ++ " . enc " ) ( encodeCube 5 inp ) Stellenwert der do-Notation Universität Bielefeld Programmieren in Haskell Giegerich Die do-Notation ist überaus hilfreich für zustandsbasierte Programmierug, aber sie ist nur “syntaktischer Zucker”, also eine bequeme Schreibweise für Programme, die man auch ohne sie programmieren kann diese andere Programmierung erklärt die do-Notation in “normalem” Haskell, aber diese Erklärung der do-Notation muss man nicht kennen, um sie zu benutzen ... es sei denn, man will sie erweitern für den eigenen Bedarf Prüfungsvorbere Imperative Programmierung IO Monaden Imperativ funktional ... Universität Bielefeld Programmieren in Haskell Giegerich Wie bringt man die “Aktionen” auf “Zuständen” in einer funktionalen Welt unter? Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Imperativ funktional ... Universität Bielefeld Programmieren in Haskell Giegerich Wie bringt man die “Aktionen” auf “Zuständen” in einer funktionalen Welt unter? Funktionsanwendung z = f x y oder z = (f $ x ) $ y ersetzen durch Operation, die besagt Wende f auf s, x, und y an und produziere s’ und z Wende f’ auf s’, x, y und z an und produziere s” und z” us so weiter, ohne dass man die Folge s, s’, ... explizit hinschreiben muss Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Monaden Universität Bielefeld Programmieren in Haskell Monaden sind eine mathematisches Struktur, wie Gruppe, Ring, Körper, usw. dort untersucht in der der Kategorientheorie Hier: eine Klasse von Daten mit Operationen auf diesen, die bestimmte Eigenschaften besitzen Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Monaden Universität Bielefeld Programmieren in Haskell Monaden sind eine mathematisches Struktur, wie Gruppe, Ring, Körper, usw. dort untersucht in der der Kategorientheorie Hier: eine Klasse von Daten mit Operationen auf diesen, die bestimmte Eigenschaften besitzen Grundidee: Statt Datentyp a verwendet man Typ M a Funktionsanwendung f a ersetzt durch a »= f, direkte Anwendung f (M a) ist durch den Typ ausgeschlossen wobei »= neben der Berechnung von f a weitere Geschäfte verrichten kann ... Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Besonderheit der Monaden Universität Bielefeld Programmieren in Haskell Giegerich Monaden sind nicht einfach zu verstehen, weil Prüfungsvorbere die Funktionsanwendung die grundlegendste Operation der funktionalen Programmierung ist, genau diese jetzt durch etwas (fast) Beliebiges ersetzt wird, das in jeder Monade anders ist und was wir auch selbst definieren könnne für neue Monaden Konkrete Monaden sind Typen, die Instanz der Typklasse Monad sind Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Funktionen auf Monaden Universität Bielefeld Programmieren in Haskell Giegerich 1 2 In Haskell-Notation: ( > >=) :: m a return :: a -> ( a -> m b ) -> m b -> m a Prüfungsvorbere Imperative Programmierung 3 4 5 ( > >) fail :: m a -> m b :: String -> m a -> m b IO Monaden Bedeutung der Do-Notation Maybe Listen a und b: beliebige Typen m a und m b: ihre Werte in Monade verpackt (>>=) und (>>) werden “bind” oder “bindto” ausgesprochen Monadenfunktionen 1 2 ( > >=) :: m a return :: a Universität Bielefeld -> ( a -> m b ) -> m b -> m a 5 Giegerich Prüfungsvorbere 3 4 Programmieren in Haskell ( > >) :: m a -> m b fail :: String -> m a Was leistet >>=? -> m b Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe “Entpackt” a aus der Monade, wendet f darauf an, liefert “verpacktes” Ergebnis, das weiter verwendet werden kann in der Form x >>= f >>= g >>= h ... Das “Auspacken” geschieht bei jeder Monade auf eigene Art – und es kann auch direkt das Ergebnis erzeugen. Listen Monadenfunktionen Universität Bielefeld Programmieren in Haskell Giegerich 1 2 ( > >=) :: m a return :: a -> ( a -> m b ) -> m b -> m a 3 4 5 ( > >) :: m a -> m b fail :: String -> m a Was leistet return? -> m b Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Verpacken eines Werts a in der Monade, damit man mit >>= und >> darauf arbeiten kann Monadenfunktionen 1 2 ( > >=) :: m a return :: a Universität Bielefeld -> ( a -> m b ) -> m b -> m a 3 4 5 Programmieren in Haskell Giegerich Prüfungsvorbere ( > >) :: m a -> m b fail :: String -> m a Was leistet >>? -> m b Imperative Programmierung IO Monaden Bedeutung der Do-Notation 1 Machmal möchte man eine Konstante für eine Funktion einsetzen: > count xs = sum ( map (\ x - >1) xs ) x >> f setzt x voraus, um f zu berechnen, also werden Ketten von Operationen sequenzialisiert durch x >> f1 >> f2 >> f3 ... Maybe Listen Monadenfunktionen 1 2 ( > >=) :: m a return :: a Universität Bielefeld -> ( a -> m b ) -> m b -> m a 3 4 5 Programmieren in Haskell Giegerich Prüfungsvorbere ( > >) :: m a -> m b fail :: String -> m a Was leistet >>? -> m b Imperative Programmierung IO Monaden Bedeutung der Do-Notation 1 Machmal möchte man eine Konstante für eine Funktion einsetzen: > count xs = sum ( map (\ x - >1) xs ) x >> f setzt x voraus, um f zu berechnen, also werden Ketten von Operationen sequenzialisiert durch x >> f1 >> f2 >> f3 ... Beispiel: Sukzessives Schreiben von Output Maybe Listen Monadenfunktionen Universität Bielefeld Programmieren in Haskell Giegerich 1 2 ( > >=) :: m a return :: a -> ( a -> m b ) -> m b -> m a 3 4 5 ( > >) :: m a -> m b fail :: String -> m a Was leistet fail? -> m b Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Erzeugen eines Fehler-Strings, mit dem die Rechnung abbricht Monaden als Instanzen Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Monaden sind eine Typklasse: Monad ihr gehören alle Typen an, auf denen man die Monadenfunktionen definiert hat Monad ist vordefiniert, vergleichbar anderen Typklassen wie Show, Eq, Ord, Num jeder konkrete Typ kann zur Instanz der Typklasse gemacht werden Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Typklasse Monad Universität Bielefeld Programmieren in Haskell Giegerich Vordefinierte Typklasse: 1 2 3 4 (Achtung: m ist eine Variable für einen einstelligen Typ-Konstruktor!) Prüfungsvorbere infixl 1 > >= , >> class Monad m where ( > >=) :: m a -> ( a -> m b ) -> m b return :: a -> m a Imperative Programmierung IO Monaden Bedeutung der Do-Notation 5 Maybe 6 7 ( > >) fail :: m a -> m b :: String -> m a -> m b Listen Typklasse Monad Universität Bielefeld Programmieren in Haskell Giegerich Vordefinierte Typklasse: 1 2 3 4 (Achtung: m ist eine Variable für einen einstelligen Typ-Konstruktor!) Prüfungsvorbere infixl 1 > >= , >> class Monad m where ( > >=) :: m a -> ( a -> m b ) -> m b return :: a -> m a Imperative Programmierung IO Monaden Bedeutung der Do-Notation 5 Maybe 6 7 ( > >) fail :: m a -> m b :: String -> m a -> m b 6 7 8 m >> k fail s = m > >= \ _ -> k = error s -- default -- default Listen Monad-Laws 1 return gibt nur sein Argument zurück und führt keine weiteren Berechnungen durch: m >>= return = m return x >>= f = f x 2 >>= ist assoziativ: (m >>= f) >>= g = m >>= (\x -> (f x >>= g)) analog zur Komposition von Funktionen (m . f ) . g = m . (f . g) Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Monad-Laws 1 return gibt nur sein Argument zurück und führt keine weiteren Berechnungen durch: m >>= return = m return x >>= f = f x 2 >>= ist assoziativ: (m >>= f) >>= g = m >>= (\x -> (f x >>= g)) analog zur Komposition von Funktionen (m . f ) . g = m . (f . g) Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Analog muss (<<) assoziativ sein: (a >> b) >> c = a >> (b >> c) fail muss die Berechnung abbrechen NB: Diese Eigenschaften werden von Monaden-Instanzen gefordert, können aber vom Compiler nicht überprüft werden! Beispiel: Maybe Monad 1 2 data Maybe a = Just a | Nothing Universität Bielefeld Programmieren in Haskell Giegerich 3 4 deriving ( Show , Eq ) Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Beispiel: Maybe Monad 1 2 data Maybe a = Just a | Nothing Universität Bielefeld Programmieren in Haskell Giegerich 3 4 deriving ( Show , Eq ) 5 6 7 8 9 instance Monad Maybe where ( Just x ) > >= k = k x Nothing > >= k = Nothing return x = Just x Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Beispiel: Maybe Monad 1 2 data Maybe a = Just a | Nothing Universität Bielefeld Programmieren in Haskell Giegerich 3 4 5 6 7 8 9 deriving ( Show , Eq ) Prüfungsvorbere Imperative Programmierung instance Monad Maybe where IO ( Just x ) > >= k = k x Monaden Nothing > >= k = Nothing return x = Just x Beispiele: Just 1 > >= \ x -> Just 2 > >= \ y -> return ( x + y ) ( ) Just 1 > >= \ x -> Nothing > >= \ y -> return ( x + y ) ( ) Bedeutung der Do-Notation Maybe Listen Notation ...? Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Im wesentlichen hat man einen monadischen Wert m darauf angewandte Ketten von >>= und >> Operationen Das ist einfach, sieht aber nicht besonders übersichtlich aus ... Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Do-Notation (Do-Expression) Syntaktischer Zucker, um >>= Ketten schöner hinschreiben zu können. Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Do-Notation (Do-Expression) Syntaktischer Zucker, um >>= Ketten schöner hinschreiben zu können. m > >= f = do { x <- m ; f x } Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Do-Notation (Do-Expression) Syntaktischer Zucker, um >>= Ketten schöner hinschreiben zu können. m > >= f = do { x <- m ; f x } bzw. m > >= f = do x <- m f x Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Do-Notation (Do-Expression) Syntaktischer Zucker, um >>= Ketten schöner hinschreiben zu können. m > >= f = do { x <- m ; f x } bzw. m > >= f = do x <- m f x und m1 >> m2 = do _ <- m1 _ <- m2 Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Do-Notation (Do-Expression) Syntaktischer Zucker, um >>= Ketten schöner hinschreiben zu können. m > >= f = do { x <- m ; f x } bzw. m > >= f = do x <- m f x und m1 >> m2 = do _ <- m1 _ <- m2 bzw. m1 >> m2 = do m1 m2 Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Do-Notation Universität Bielefeld Programmieren in Haskell Giegerich 1 2 Allgemeines Übersetzungsschema: m1 > >= \ x_1 -> m_2 > >= \ x_2 -> ... ... m_n > >= \ x_n -> return ... Prüfungsvorbere Imperative Programmierung 3 4 5 6 7 8 9 10 IO = do Monaden x_1 <x_2 <x_3 <... x_n <return m_1 m_2 m_3 m_n ... Bedeutung der Do-Notation Maybe Listen Beobachtungen Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung >>= (bind-Operator) gibt eine Reihenfolge vor — Schachtelung ist beliebig (Assoziativität) IO Monaden Bedeutung der Do-Notation Maybe Listen Maybe-Beispiel Universität Bielefeld Programmieren in Haskell 1 2 3 4 do Giegerich x <- Just 1 y <- Just 2 return ( x + y ) Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Maybe-Beispiel Universität Bielefeld Programmieren in Haskell 1 2 3 4 do Giegerich x <- Just 1 y <- Just 2 return ( x + y ) Prüfungsvorbere Imperative Programmierung IO 1 2 Zum Ausprobieren in Hugs: Monaden 5 + do {x < - Just 1; y <- Just 2; return ( x + y )} Just 3 == do {x < - Just 1; y <- Just 2; return ( x + y )} Bedeutung der Do-Notation Maybe Listen Maybe-Beispiel Universität Bielefeld Programmieren in Haskell 1 do Giegerich x <- Just 1 y <- Just 2 return ( x + y ) 2 3 4 Prüfungsvorbere Imperative Programmierung IO 1 2 Zum Ausprobieren in Hugs: Monaden 5 + do {x < - Just 1; y <- Just 2; return ( x + y )} Just 3 == do {x < - Just 1; y <- Just 2; return ( x + y )} Bedeutung der Do-Notation Maybe Listen 5 6 7 8 9 do x <- Just 1 y <- Nothing return ( x + y ) Maybe-Beispiel 1 f dict = do 2 x <- lookup " alpha " dict y <- lookup " beta " dict z <- lookup " gamma " dict return ( x + y + z ) lookup :: String -> Dict -> Maybe Int 3 4 5 6 Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Maybe-Beispiel 1 f dict = do 2 x <- lookup " alpha " dict y <- lookup " beta " dict z <- lookup " gamma " dict return ( x + y + z ) lookup :: String -> Dict -> Maybe Int 3 4 5 6 statt sowas wie: Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe 6 7 8 9 10 11 12 Listen f dict = if isJust x && isJust y && isJust z then Just ( fromJust x + fromJust y + fr else Nothing where x = lookup " alpha " dict y = lookup " beta " dict z = lookup " gamma " dict Monad-Laws in do-Notation Universität Bielefeld Programmieren in Haskell Giegerich 1 do { x <- m ; return x } = m 2 do { y <- return x ; f y 3 Assoziativität von >>=: do { y <- do { x <- m ; f x } ; g y } } = f x Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe = do { x <- m ; do { y <- f x ; g y } } = do { x <- m ; y <- f x ; g y } Listen Do-Notation — let-Deklaration Universität Bielefeld Programmieren in Haskell Giegerich 1 2 3 Weiterer syntaktischer Zucker — statt let a = 42 in do print a Prüfungsvorbere Imperative Programmierung IO Monaden 1 2 3 kann man auch schreiben: do let a = 42 print a Bedeutung der Do-Notation Maybe Listen Listen-Beispiel Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere 1 2 -- data [ a ] = a : [ a ] | -[] Imperative Programmierung IO 3 Monaden 4 5 6 instance Monad [] where ( > >=) l f = concat ( map f l ) return x = [x] Bedeutung der Do-Notation Maybe Listen Listen-Beispiel mit selbstdefinierten Datentyp Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere 1 2 data List a = Cons a ( List a ) | Nil Imperative Programmierung IO 3 Monaden 4 5 6 instance Monad List where ( > >=) l f = concatList ( mapList f l ) return x = [x] Bedeutung der Do-Notation Maybe Listen Listen-Beispiel Universität Bielefeld Programmieren in Haskell 1 2 -- data [ a ] = a : [ a ] | -[] 3 4 5 6 instance Monad [] where ( > >=) l f = concat ( map f l ) return x = [x] Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Listen-Beispiel Universität Bielefeld Programmieren in Haskell 1 2 -- data [ a ] = a : [ a ] | -[] 3 4 5 6 instance Monad [] where ( > >=) l f = concat ( map f l ) return x = [x] do x <- [1 ,2] y <- [3 ,4] return ( x * y ) Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Listen-Beispiel Universität Bielefeld Programmieren in Haskell 1 2 -- data [ a ] = a : [ a ] | -[] 3 4 5 6 instance Monad [] where ( > >=) l f = concat ( map f l ) return x = [x] do x <- [1 ,2] y <- [3 ,4] return ( x * y ) = > [3 ,4 ,6 ,8] Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Listen-Beispiel Universität Bielefeld Programmieren in Haskell 1 2 -- data [ a ] = a : [ a ] | -[] 3 4 5 6 instance Monad [] where ( > >=) l f = concat ( map f l ) return x = [x] do x <- [1 ,2] y <- [3 ,4] return ( x * y ) = > [3 ,4 ,6 ,8] Analog zu folgender Listenbeschreibung: [ x * y | x <- [1 ,2] , y <- [3 ,4] ] Giegerich Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Beobachtungen zur do-Notation Universität Bielefeld Programmieren in Haskell Giegerich Prüfungsvorbere sieht sehr imperativ aus „Zuweisungen“zu Variablen → aber nur in Single-Assignment (SA) Form Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen Zurück zum IO in Haskell Universität Bielefeld Programmieren in Haskell Giegerich mit der Monade IO Prüfungsvorbere IO als einstelliger Typkonstruktor Imperative Programmierung IO als ADT IO importieren mit import IO Monaden Ausgabe mit Typ IO () Eingabe mit Typ IO String, IO Int, etc Bedeutung der Do-Notation Maybe Listen Zurück zum IO in Haskell Universität Bielefeld Programmieren in Haskell Giegerich mit der Monade IO Prüfungsvorbere IO als einstelliger Typkonstruktor Imperative Programmierung IO als ADT IO importieren mit import IO Monaden Ausgabe mit Typ IO () Eingabe mit Typ IO String, IO Int, etc → Monadeneigenschaft definiert die Reihenfolge IO-Fehler durch error Bedeutung der Do-Notation Maybe Listen IO-Monad Beobachtungen Universität Bielefeld Programmieren in Haskell Giegerich Referential-Transparency? Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen IO-Monad Beobachtungen Universität Bielefeld Programmieren in Haskell Giegerich Referential-Transparency? → ja — nur sind die Werte von IO a verborgen (ADT-Eigenschaft) wie kommt der eigene Code z.B. an den Char-Wert bei IO String? Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe Listen IO-Monad Beobachtungen Universität Bielefeld Programmieren in Haskell Giegerich Referential-Transparency? → ja — nur sind die Werte von IO a verborgen (ADT-Eigenschaft) wie kommt der eigene Code z.B. an den Char-Wert bei IO String? Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe → durch die Definition von >>= Listen IO-Monad Beobachtungen Universität Bielefeld Programmieren in Haskell Giegerich Referential-Transparency? → ja — nur sind die Werte von IO a verborgen (ADT-Eigenschaft) wie kommt der eigene Code z.B. an den Char-Wert bei IO String? Prüfungsvorbere Imperative Programmierung IO Monaden Bedeutung der Do-Notation Maybe → durch die Definition von >>= eindeutige Sequenzierung der IO-Funktionen durch Monadeneigenschaft Listen Anwendungsgebiete Universität Bielefeld Programmieren in Haskell Giegerich Wichtigste Anwendung der Monaden Input / Output Prüfungsvorbere Imperative Programmierung Fehlerbehandlung IO zustandbasierte Programme Monaden destructive updates (!!) Pssst: Verpackung des Zustands in einer Monade erlaubt dem Compiler speichereffiziente Implementierung durch destruktive Updates ... Bedeutung der Do-Notation Maybe Listen