Fortgeschrittene Techniken der Funktionalen Programmierung Vorlesung vom 03.11.09: Mehr über Monaden Christoph Lüth, Dennis Walter Universität Bremen Wintersemester 2009/10 1 Heute gibt’s: I Monaden, mehr Monaden, und noch mehr Monaden I Die Monaden der Standardbücherei I Referenz: http://www.haskell.org/all˙about˙monads/html 2 Fahrplan I 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 3 Die Identitätsmonade 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 Fehlermonaden I Erste Nährung: Maybe I Maybe kennt nur Nothing, daher strukturierte Fehler: 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 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 Nachteil: Fester Fehlertyp I Lösung: Typklassen 5 Die Monade Control.Monad.Error I Typklasse Error für Fehler c l a s s E r r o r a where noMsg : : a strMsg : : S t r i n g → a I 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 MonadError ( E i t h e r e ) where throwError = Left ( Left e ) ‘ catchError ‘ handler = handler e a ‘ catchError ‘ = a 6 Die Zustandsmonade I Zustandsübergang als Funktion newtype S t a t e s a = S t a t e { unwrap : : ( s → ( a , s ) ) } 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 Nachteil 1: Zustandsübergang nicht-strikt (insbesondere lazy)! I I Lösung: Strikter Zustandsübergang— Control.Monad.ST Nachteil 2: Zustandsübergang ≡ Funktion I Lösung: Typklassen 7 Die Monad Control.Monad.State I Typklasse State für Zustand lesen/schreiben: c l a s s MonadState m s where get : : m s put : : s → m ( ) I 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 ) I Aber: manchmal liest man nur, manchmal schreibt man nur. . . 8 Die Lesemonade I Intuition: Werte der Eingabe e lesen und verabeiten. I Lese-Teil der Zustandsmonade 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) g e 9 Die Monade Control.Monad.Reader 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 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 ) 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 10 Die Schreibmonade I Produziert einen Strom von Werten I Kein Zugriff auf geschriebene Werte möglich I Beispiel: “Logging” 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 Abstraktion: auch über Listen von Ausgabewerten 11 Die Monade Control.Monad.Writer I Typklasse Monoid: Verallgemeinerte Listen c l a s s ( Monoid pass :: m listen :: m tell :: w instance pass listen tell 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) 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 ) 12 Die Listenmonade I Listen sind Monaden: 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? 13 Der Monade Set I 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 . . . 14 Der Continuationmonade I Auswertungskontext wird explizit modelliert. 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 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 ) 15 Control.Monad.Cont I 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 → k a )) k Lieber nicht benutzen! 16 Exkurs: Was ist eigentliche eine Monade? I Monade: Konstrukt aus Kategorientheorie I Monade ∼ = (verallgemeinerter) Monoid I Monade: gegeben durch algebraische Theorien I Operationen endlicher (beschränkter) Aritität I Gleichungen I Beispiele: Maybe, List, Set, State, . . . I Monaden in Haskell: computational monads I Strukturierte Notation für Berechnungsparadigmen I Beispiel: Rechner mit Fehler, Nichtdeterminismus, Zustand, . . . 17 Kombination von Monaden: Das Problem I Gegeben zwei Monaden: c l a s s Monad m1 where . . . c l a s s Monad m2 where . . . I 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 ) ) I Problem: Monadengesetze gelten nicht. I Lösung: Nächste Vorlesung 18 Zusammenfassung I Monaden sind praktische Abstraktion I 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 . . . 19