Heute gibt’s: Fortgeschrittene Techniken der Funktionalen Programmierung Vorlesung vom 03.11.09: Mehr über Monaden I Christoph Lüth, Dennis Walter Universität Bremen Monaden, mehr Monaden, und noch mehr Monaden I Die Monaden der Standardbücherei I Referenz: http://www.haskell.org/all˙about˙monads/html Wintersemester 2009/10 2 1 Fahrplan I Die Identitätsmonade Teil I: Monaden und fortgeschrittene Typen I Einführung, Wiederholung I Zustände, Zustandsübergänge und IO I Reader/Writer, Nichtdeterminismus, Ausnahmen I Monadentransformer I Teil II: Fortgeschrittene Datenstrukturen I Teil III: Nebenläufigkeit I Teil IV: The Future of Programming I Die allereinfachste Monade: type I d a = a i n s t a n c e Monad I d where return a = a b = f = f b 4 3 Fehlermonaden I Erste Nährung: Maybe I Maybe kennt nur Nothing, daher strukturierte Fehler: Die Monade Control.Monad.Error I c l a s s E r r o r a where noMsg : : a strMsg : : S t r i n g → a data E i t h e r a b = L e f t a | R i g h t b type E r r o r a = Either String a I Nachteil: Fester Fehlertyp I Lösung: Typklassen Fehlermonade parametrisiert über e: c l a s s ( Monad m) ⇒ MonadError e m where throwError : : e → m a catchError : : m a → (e → m a) → m a i n s t a n c e Monad ( E i t h e r S t r i n g ) where ( R i g h t a ) = f = f a ( L e f t l ) = f = L e f t l return b = Right b I Typklasse Error für Fehler i n s t a n c e MonadError ( E i t h e r e ) where throwError = Left ( Left e ) ‘ catchError ‘ handler = handler e a ‘ catchError ‘ = a 5 Die Zustandsmonade I 6 Die Monad Control.Monad.State Zustandsübergang als Funktion I newtype S t a t e s a = S t a t e { unwrap : : ( s → ( a , s ) ) } c l a s s MonadState m s where get : : m s put : : s → m ( ) i n s t a n c e Monad ( S t a t e s ) where return a = State $ λs → (a , s ) ( S t a t e g ) = f = S t a t e ( u n c u r r y g . unwrap f ) I I Nachteil 1: Zustandsübergang nicht-strikt (insbesondere lazy)! I I Typklasse State für Zustand lesen/schreiben: Zustandsmonade parametrisiert über State: i n s t a n c e MonadState ( S t a t e s ) s where get = State $ λs → ( s , s ) put s = S t a t e $ λ → ( ( ) , s ) Lösung: Strikter Zustandsübergang— Control.Monad.ST Nachteil 2: Zustandsübergang ≡ Funktion I I Lösung: Typklassen 7 Aber: manchmal liest man nur, manchmal schreibt man nur. . . 8 Die Lesemonade I Die Monade Control.Monad.Reader Intuition: Werte der Eingabe e lesen und verabeiten. I Lese-Teil der Zustandsmonade I Wie vorher: Abstraktion der Leseoperationen I Neu: Lokaler Zustand c l a s s MonadReader e m where ask :: m e local :: (e → e) → m a → m a newtype R e a d e r e a = R e a d e r ( e → a ) i n s t a n c e Monad ( R e a d e r e ) where return a = R e a d e r $ λe → a ( R e a d e r r ) = f = R e a d e r $ λe → l e t R e a d e r g = f ( r e ) i n I Eingabe wird nicht modifiziert. I Beispiel: Lesen aus Symboltabelle (Gegenbeispiel: Datei) i n s t a n c e MonadReader ( R e a d e r e ) where ask = Reader i d l o c a l f c = R e a d e r $ λe → r u n R e a d e r c ( f e ) g e a s k s : : ( MonadReader e m) ⇒ ( e → a ) → m a a s k s s e l = a s k = r e t u r n . s e l 9 Die Schreibmonade 10 Die Monade Control.Monad.Writer I I Produziert einen Strom von Werten I Kein Zugriff auf geschriebene Werte möglich I Beispiel: “Logging” c l a s s ( Monoid pass :: m listen :: m tell :: w instance pass listen tell newtype W r i t e r w a = W r i t e r ( a , [ w ] ) i n s t a n c e Monad ( W r i t e r w) where return a = W r i t e r ( a , [] ) ( W r i t e r ( a , w) ) = f = l e t W r i t e r ( a ’ , w ’ ) = f a i n W r i t e r ( a ’ , w++ w ’ ) I Typklasse Monoid: Verallgemeinerte Listen w , Monad m) ⇒ MonadWriter w m where ( a , w → w) → m a a → m ( a , w) → m () MonadWriter ( W r i t e r w) where ( W r i t e r ( ( a , f ) ,w) ) = W r i t e r ( a , f w) ( W r i t e r ( a , w) ) = W r i t e r ( ( a , w) ,w) s = Writer (() , s ) listens : : ( MonadWriter w m) ⇒ (w → w) → m a → m ( a , w) l i s t e n s f m = do ( a , w) ← m; r e t u r n ( a , f w) Abstraktion: auch über Listen von Ausgabewerten c e n s o r : : ( MonadWriter w m) ⇒ (w → w) → m a → m a c e n s o r f m = p a s s $ do a ← m; r e t u r n ( a , f ) 11 Die Listenmonade I 12 Der Monade Set Listen sind Monaden: I i n s t a n c e Monad [] where m = f = concatMap f m return x = [ x ] fail s = [] I Intuition: f :: a→ [b] Liste der möglichen Resultate I Reihenfolge der Möglichkeiten relevant? Data.Set sind Monaden: i n s t a n c e Monad S e t where m = f = S e t . u n i o n s ( S e t . map f m) r e t u r n x = Set . s i n g l e t o n x fail s = S e t . empty I Nicht vordefiniert . . . 13 Der Continuationmonade I 14 Control.Monad.Cont Auswertungskontext wird explizit modelliert. I newtype Cont r a = Cont { r u n C o n t : : ( ( a → r ) → r ) } I r ist der Typ der gesamten Berechnung I a→ r ist der momentane Kontext callCC: GOTO für funktionale Sprachen c l a s s ( Monad m) ⇒ MonadCont m where callCC : : (( a → m b) → m a) → m a i n s t a n c e MonadCont ( Cont r ) where c a l l C C f = Cont $ λk → r u n C o n t ( f ( λa → Cont $ λ i n s t a n c e Monad ( Cont r ) where return a = Cont $ λk → k a ( Cont c ) = f = Cont $ λk → c ( λa → r u n C o n t ( f a ) k ) I 15 → k a )) k Lieber nicht benutzen! 16 Exkurs: Was ist eigentliche eine Monade? Kombination von Monaden: Das Problem I Monade: Konstrukt aus Kategorientheorie I Monade ∼ = (verallgemeinerter) Monoid c l a s s Monad m1 where . . . I Monade: gegeben durch algebraische Theorien c l a s s Monad m2 where . . . I I I Operationen endlicher (beschränkter) Aritität I Gleichungen I I Monaden in Haskell: computational monads Strukturierte Notation für Berechnungsparadigmen I Beispiel: Rechner mit Fehler, Nichtdeterminismus, Zustand, . . . 17 Zusammenfassung I I Monaden sind praktische Abstraktion Wir haben kennengelernt: I Fehlermonaden: Maybe, Either, MonadError I Zustandsmonaden: State, ST, IO I Lese/Schreibmonade: ReaderMonad, WriterMonad I Nichtdeterminusmus: [a], Data.Set I Explizite Sprünge: Continuation I Wichtiges Strukturierungsmittel für funktionale Programme I Kombination bereitet (noch) Probleme . . . Es gelten weder i n s t a n c e Monad (m1 (m2 a ) ) i n s t a n c e Monad (m2 (m1 a ) ) Beispiele: Maybe, List, Set, State, . . . I Gegeben zwei Monaden: 19 I Problem: Monadengesetze gelten nicht. I Lösung: Nächste Vorlesung 18