Damit gelten dann die "freien Theoreme" für die Typen von return und bind:
return . f = fmap f . return x >>= (g . f) = fmap f x >>= gWieso das? return :: a -> m a == Id a -> m a. links steht also der identische Funktor (dessen fmap ist ein id).
Aufgabe 1: erkläre genau, wie das freie Theorem für bind (>>=) entsteht.
Wir benötigen dazu eine instance Functor (c ->), für jedes feste c, d. h. ein
fmap :: (a -> b) -> ((c -> a) -> (c -> b))Was soll fmap f g bedeuten? Mit f :: a -> b und g :: c -> a soll fmap f g :: c -> b sein. Wir wenden einfach auf das Resultat von g die Funktion f an:
instance Functor ((->) c) where fmap f g = f . g
Wir begeben uns zur eleganteren Beschreibung in die Kleisli-Kategorie der Monade m, d. h. die Pfeile haben alle den Typ a -> m b. Dann betrachten wir statt bind die Kleisli-Komposition
(@@) :: (a -> m b) -> (b -> m c) -> (a -> m c) f @@ g = \ x -> (f x) >>= gFür diese muß gelten
f @@ (g @@ h) = (f @@ g) @@ h return @@ f = f = f @@ returnDamit hat der Bereich (a -> m b) eine Monoid-Struktur: assoziative Verknüpfung mit neutralem Element.
f x =?= (return @@ f) x = return x >>= f [ x ] >>= f = concat (map f [x]) = concat [ f x ] = f xUnd vielleicht noch f @@ (g @@ h) = (f @@ g) @@ h für Maybe: Der Typ (beider Seiten) ist wieder a -> Maybe b, wobei die einzelnen Bezeicher so aussehen (für geeignete c, d)
f :: a -> Maybe c; g :: c -> Maybe d; h :: d -> Maybe bWenden wir wieder beide Seiten auf ein x :: a an, erhalten wir
(f @@ (g @@ h)) x =?= (f @@ g) @@ h f x >>= (g @@ h) =?= (f @@ g) x >>= h = (f x >>= g) >>= hBetrachten wir den Fall f x = Nothing. Dann kommt links und rechts Nothing heraus. Wenn aber f x = Just y, dann
f x >>= (g @@ h) =?= (f @@ g) x >>= h = (f x >>= g) >>= h Just y >>= (g @@ h) =?= (Just y >>= g) >>= h (g @@ h) y =?= g y >>= hund das ist genau die Definition von (@@).
f x = (f @@ return) x = f x >>= returnUnter Benutzung der do-Notation ist die rechte Seite
f x >>= return = do { z <- f x; return z }Schreibe die andere Gleichung f = return @@ f ebenso.Aufgabe 3
Die Funktor-Instanz einer Monade bekämen wir umsonst: beweise aus den Monaden-Axiomen:fmap f x = x >>= (return . f)Aufgabe 4
Zum Üben wieder mal ein paar falsche Instanzen: Welche der Axiome erfülltfalsche-instance Monad Maybe where return x = Nothing (>>=) wie bei der richtigen InstanzFinde eine falsche instance Monad []. Sie soll sich "möglichst richtig" verhalten.Aufgabe 5
Welche der bekannten Bäume (binäre mit Schlüssel in Blättern, binär mit Schlüssel in inneren Knoten, Rose Trees) lassen sich zu Monaden machen?Nicht mit der Numerierung von früher verwechseln. Dort ging es um Bäume, aber die Monade war eine Zustandsmonade. Jetzt brauchen wir
instance Monad Tree where return :: a -> Tree a (>>=) :: Tree a -> (a -> Tree b) -> Tree bFür (>>=) heißt das: aus jedem Schlüssel wird ein eigener Baum berechnet, und diesen Baum von Bäumen müssen wir zu einem einzigen Baum zusammenkleben.
http://www.informatik.uni-leipzig.de/~joe/ mailto:joe@informatik.uni-leipzig.de