28.04.2014 Aufrufe

Monaden in Haskell

Monaden in Haskell

Monaden in Haskell

MEHR ANZEIGEN
WENIGER ANZEIGEN

Erfolgreiche ePaper selbst erstellen

Machen Sie aus Ihren PDF Publikationen ein blätterbares Flipbook mit unserer einzigartigen Google optimierten e-Paper Software.

<strong>Monaden</strong> <strong>in</strong> <strong>Haskell</strong><br />

Joachim Breitner<br />

16. November 2010<br />

<strong>Haskell</strong> vs. Kategorientheorie<br />

E<strong>in</strong>e Monade <strong>in</strong> <strong>Haskell</strong> ist e<strong>in</strong>e Typklasse mit zwei Methoden:<br />

class Monad m where<br />

(»=) :: m a → (a → m b) → m b<br />

return :: a → m a<br />

wobei die folgenden Beziehungen gelten sollten:<br />

return x »= f ≡ f x<br />

a »= return ≡ a<br />

(a »= f) »= g ≡ a »= (ńx → f x »= g).<br />

E<strong>in</strong>e Formulierung der üblichen <strong>Monaden</strong>-Def<strong>in</strong>ition für <strong>Haskell</strong> wäre<br />

class Monad m where<br />

map :: (a → b) → m a → m b<br />

return :: a → m a<br />

jo<strong>in</strong> :: m (m a) → m a<br />

wobei m Typen auf Typen abbildet, also zusammen mit map e<strong>in</strong>en Funktor Hask → Hask def<strong>in</strong>iert.<br />

Es entspricht weiter return dem ε und jo<strong>in</strong> dem µ.<br />

Aus den Bed<strong>in</strong>gungen dass ε und µ natürliche Transformationen s<strong>in</strong>d, sowie den zwei def<strong>in</strong>ierenden<br />

kommutativen Diagrammen erhalten wir <strong>in</strong> <strong>Haskell</strong>-Schreibweise folgende Eigenschaften:<br />

map g ◦ return ≡ return ◦ g<br />

map g ◦ jo<strong>in</strong> ≡ jo<strong>in</strong> ◦ map (map g)<br />

jo<strong>in</strong> ◦ map jo<strong>in</strong> ≡ jo<strong>in</strong> ◦ jo<strong>in</strong><br />

jo<strong>in</strong> ◦ return ≡ jo<strong>in</strong> ◦ map return ≡ id.<br />

Die beiden Def<strong>in</strong>itionen s<strong>in</strong>d äquivalent. Man kann<br />

map f = (ńa → a »= (return ◦ f))<br />

jo<strong>in</strong> a = a »= id<br />

bzw. a »= f = jo<strong>in</strong> (map f a)<br />

def<strong>in</strong>ieren und nachrechnen, dass die obigen Bed<strong>in</strong>gungen <strong>in</strong>e<strong>in</strong>ander übergehen.<br />

Quellen: http://www.haskell.org/haskellwiki/Category_theory/Monads<br />

http://www.haskell.org/haskellwiki/User:Michiexile/MATH198<br />

http://www.haskell.org/all_about_monads/<br />

http://comonad.com/reader/


E<strong>in</strong> kle<strong>in</strong>er <strong>Monaden</strong>zoo<br />

Im folgenden die bekanntesten <strong>Haskell</strong>-<strong>Monaden</strong>, <strong>in</strong> etwas liberalerer Syntax.<br />

Maybe<br />

(Modelliert: partielle Funktionen, Berechnungen<br />

mit Fehlerzuständen)<br />

data Maybe a = Just a | Noth<strong>in</strong>g<br />

<strong>in</strong>stance Monad Maybe where<br />

return = Just<br />

(Just x) »= k = k x<br />

Noth<strong>in</strong>g »= k = Noth<strong>in</strong>g<br />

Either e<br />

(Modelliert: Berechnungen mit Fehlermeldungen)<br />

data Either e a = Left e | Right a<br />

<strong>in</strong>stance Monad (Either e) where<br />

return = Right<br />

(Left e) »= k = Left e<br />

(Right x) »= k = k x<br />

[]<br />

(Liste. Modelliert: Nichtdeterm<strong>in</strong>ismus)<br />

data [a] = a:[a] | [ ]<br />

<strong>in</strong>stance Monad [ ] where<br />

return x = [x]<br />

[ ] »= k = [ ]<br />

(x:xs) »= k = k x ++ (xs »= k)<br />

Reader r<br />

(Leser-Monade. Modelliert: Kontext<strong>in</strong>formationen)<br />

type Reader r a = r → a<br />

<strong>in</strong>stance Monad (Reader r) where<br />

return x = ńr → x<br />

m »= k = ńr → k (m r) r<br />

Writer m<br />

(Schreiber-Monade. Modelliert: Protokollierung.<br />

(M,e,∗) muss e<strong>in</strong> Monoid se<strong>in</strong>.)<br />

type Writer m a = (m,a)<br />

<strong>in</strong>stance Monoid m ⇒ Monad Writer where<br />

return x = (e, x)<br />

m »= k = let (m, y) = m<br />

(m’, z) = k a<br />

<strong>in</strong> (m ∗ m’, z)<br />

State s<br />

(Zustands-Monade. Modelliert: Berechnungen<br />

mit Zustand)<br />

type State s a = s → (a,s)<br />

<strong>in</strong>stance State s where<br />

return x = ńs → (x,s)<br />

m »= k = ńs → let (y, s’) = m s<br />

<strong>in</strong> k y s’<br />

Cont r<br />

(Fortführungs-Monade. Modelliert Sprünge im<br />

Programmablauf)<br />

type Cont r a = (a → r) → r<br />

<strong>in</strong>stance Monad (Cont r) where<br />

return x = ńc → c x<br />

m »= k = ńc → m (ńa → k a c)<br />

Identity<br />

(Modelliert: re<strong>in</strong>e Funktionen)<br />

type Identity a = a<br />

<strong>in</strong>stance Monad Identity where<br />

return = id<br />

m »= k = k m<br />

IO<br />

(Modelliert: Berechnungen, die mit der „echten<br />

Welt“ kommunizieren, etwa Dateizugriffe.<br />

Implementierung ist Compiler-Geheimnis!)<br />

type IO = ?<br />

<strong>in</strong>stance Monad IO where<br />

return = ?<br />

m »= k = ?<br />

Do-Notation<br />

<strong>Haskell</strong> unterstützt e<strong>in</strong>e spezielle Syntax für<br />

monadische Berechnungen. So steht etwa<br />

ma<strong>in</strong> = do x ← getL<strong>in</strong>e<br />

putStr ("You said " ++ x)<br />

return 3<br />

für<br />

ma<strong>in</strong> = getL<strong>in</strong>e »= (ńx →<br />

(putStr ("You said " ++ x) »= (ń_ →<br />

return 3))).

Hurra! Ihre Datei wurde hochgeladen und ist bereit für die Veröffentlichung.

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!