16.11.2013 Aufrufe

Monaden Motivation Definition der Typklasse Monad Definition der ...

Monaden Motivation Definition der Typklasse Monad Definition der ...

Monaden Motivation Definition der Typklasse Monad Definition der ...

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>Motivation</strong><br />

<strong><strong>Monad</strong>en</strong><br />

Horst Hansen<br />

Hochschule für Technik und Wirtschaft Berlin<br />

Studiengang Angewandte Informatik<br />

Sommersemester 2012<br />

<strong><strong>Monad</strong>en</strong> sind Konstruktionen, die auf polymorphen (generischen)<br />

Typen aufbauen.<br />

<strong><strong>Monad</strong>en</strong> selbst werden definiert als instance-Deklarationen <strong>der</strong><br />

monadischen Klassen Functor, <strong>Monad</strong> o<strong>der</strong> <strong>Monad</strong>Plus. Von<br />

monadischen Klassen kann nicht abgeleitet werden.<br />

Neben dem polymorphen Typ IO sind auch die polymorphen<br />

Typen Maybe und Listen ([]) monadische Klassen.<br />

c○ Horst Hansen <strong><strong>Monad</strong>en</strong> 1<br />

c○ Horst Hansen <strong><strong>Monad</strong>en</strong> 2<br />

<strong>Definition</strong> <strong>der</strong> <strong>Typklasse</strong> <strong>Monad</strong><br />

In <strong>der</strong> Klasse <strong>Monad</strong> werden die Basisfunktionen einer <strong>Monad</strong>e<br />

definiert.<br />

1 class <strong>Monad</strong> m where<br />

2 (>>=) :: m a -> (a -> m b) -> m b<br />

3 (>>) :: m a -> m b -> m b<br />

4 return :: a -> m a<br />

5 m >> k = m >>= \_ -> k<br />

Alle instance-Deklarationen von <strong>Monad</strong> müssen die folgenden<br />

Gesetze erfüllen:<br />

1 return a >>= k = k a<br />

2 m >>= return = m<br />

3 m >>= (\x -> k x >>= h) = (m >>= k) >>= h<br />

Instanzen von <strong>Monad</strong> und Functor müssen zusätzlich dieses<br />

Gesetz erfüllen:<br />

1 fmap f xs = xs >>= return . f<br />

<strong>Definition</strong> <strong>der</strong> <strong>Typklasse</strong> Functor<br />

Bevor wir uns daran machen, die Funktionen <strong>der</strong> <strong>Typklasse</strong> <strong>Monad</strong><br />

zu verstehen, schauen wir uns erst einmal die einfachere <strong>Typklasse</strong><br />

Functor an, die wir anschließend benötigen werden.<br />

1 class Functor f where<br />

2 fmap :: (a -> b) -> f a -> f b<br />

Die hier deklarierte Funktion fmap ist eine Verallgemeinerung <strong>der</strong><br />

schon bekannten Funktion map:<br />

1 map :: (a -> b) -> [a] -> [b]<br />

Man beachte, daß f eine freie Typvariable ist, die auf zwei weitere<br />

freie Typvariablen a und b angewendet wird!<br />

c○ Horst Hansen <strong><strong>Monad</strong>en</strong> 3<br />

c○ Horst Hansen <strong><strong>Monad</strong>en</strong> 4


Gesetze in <strong>der</strong> <strong>Typklasse</strong> Functor<br />

Instanz-Deklaration zu <strong>der</strong> <strong>Typklasse</strong> Functor<br />

In allen Instanzen <strong>der</strong> <strong>Typklasse</strong> Functor müssen für die Funktion<br />

fmap die folgenden Gleichungen erfüllt sein:<br />

1 fmap id = id<br />

2 fmap (f . g) = fmap f . fmap g<br />

Diese Gesetze dücken aus, daß die Funktion fmap we<strong>der</strong> den<br />

vorliegenden Behältertyp verän<strong>der</strong>t noch die Inhaltselemente<br />

an<strong>der</strong>s anordnet.<br />

Somit sollte das Folgende funktionieren: Wenn wir einen<br />

polymorphen (generischen) Typ Tree a definiert haben durch<br />

1 data Tree a = Leaf a | Branch (Tree a) (Tree a)<br />

sollte es möglich sein, zu definieren:<br />

1 instance Functor Tree where<br />

2 fmap f (Leaf x) =Leaf (f x)<br />

3 fmap f (Branch t1 t2)=Branch (fmap f t1) (fmap f t2)<br />

Diese Instanzdeklaration besagt, daß Tree und nicht Tree a eine<br />

Instanz <strong>der</strong> <strong>Typklasse</strong> Functor ist. Dadurch kann die Funktion<br />

map auf verschiedene Behältertypen mit beliebigen Inhaltstypen in<br />

<strong>der</strong> gleichen Weise angewendet werden.<br />

c○ Horst Hansen <strong><strong>Monad</strong>en</strong> 5<br />

c○ Horst Hansen <strong><strong>Monad</strong>en</strong> 6<br />

Schreibweisen in Haskell<br />

<strong>Definition</strong> <strong>der</strong> <strong>Typklasse</strong> <strong>Monad</strong><br />

Die Anwendung von <strong>Typklasse</strong>n auf Typen wird in Haskell genauso<br />

notiert wie die Anwendung von Funktionen auf ihre Argumente.<br />

So wird <strong>der</strong> Typausdruck T a b parsiert als (T a) b.<br />

Für Funktionen ist (->) <strong>der</strong> Typkonstruktor, d.h. (->) f g und<br />

f -> g bedeutet dasselbe. Ebenso sind die Typen [] a und [a]<br />

dasselbe. Entsprechendes gilt für die Tupelkonstruktoren (,),<br />

(,,) usw.<br />

Um Fehler in <strong>der</strong> Anwendung von <strong>Typklasse</strong>n auf Typen prüfen zu<br />

können, ist in Haskell ein Metatypsystem implementiert. Typen von<br />

Typen werden als hier als kind bezeichnet (siehe [HPF99], S.26).<br />

Kommen wir jetzt zur <strong>Typklasse</strong> <strong>Monad</strong> zurück.<br />

1 class <strong>Monad</strong> m where<br />

2 (>>=) :: m a -> (a -> m b) -> m b<br />

3 (>>) :: m a -> m b -> m b<br />

4 return :: a -> m a<br />

5 m >> k = m >>= \_ -> k<br />

Die zwei Basisfunktionen einer <strong>Monad</strong>e sind >>= (gesprochen:<br />

bind) und return.<br />

Die bind-Funktion kombiniert zwei monadische Datenwerte.<br />

Die return-Funktion fügt dem monadischen Behälter einen<br />

Datenwert hinzu.<br />

c○ Horst Hansen <strong><strong>Monad</strong>en</strong> 7<br />

c○ Horst Hansen <strong><strong>Monad</strong>en</strong> 8


Erläuterung <strong>der</strong> bind-Funktion<br />

do-Syntax<br />

ma >>= \v -> mb kombiniert einen monadischen Behälter ma,<br />

<strong>der</strong> Werte vom Typ a enthält und eine Funktion, die auf einem<br />

Wert v vom Typ a arbeitet. Sie liefert einen neuen monadischen<br />

Behälter mb als Ergebnis. Das Ergebnis ist somit die Kombination<br />

von ma und mb zu einem neuen monadischen Behälter, <strong>der</strong> den<br />

Wert b enthält.<br />

Die genaue Bedeutung <strong>der</strong> bind-Funktion hängt von <strong>der</strong> konkreten<br />

<strong>Monad</strong>e ab.<br />

Die do-Syntax von Haskell ist durch die folgenden <strong>Definition</strong>en<br />

gegeben:<br />

1 do e1 ; e2 = e1 >> e2<br />

2 do p >= \p -> e2<br />

c○ Horst Hansen <strong><strong>Monad</strong>en</strong> 9<br />

c○ Horst Hansen <strong><strong>Monad</strong>en</strong> 10<br />

Quellen<br />

[CK04] Chakravarty, M.M.T., Keller, G.C.: Einführung in die<br />

Programmierung mit Haskell; Pearson Studium, 2004<br />

[HPF99] Hudak, P., Peterson, J., Fasel, J.H.: A Gentle Introduction to<br />

Haskell 98; from somewhere in the web<br />

[OSG08] O’Sullivan, B., Stewart, D., Goerzen, J.: Real World Haskell;<br />

http://book.realworldhaskell.org/read/index.html, 2011<br />

[Wadl95] Wadler, P.: <strong>Monad</strong>s for functional programming; in: LNCS<br />

925, Springer Verlag, 1995<br />

c○ Horst Hansen <strong><strong>Monad</strong>en</strong> 11

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

Erfolgreich gespeichert!

Leider ist etwas schief gelaufen!