module MonadZero where
class Monad m => MonadZero m where
zero :: m a
guard :: MonadZero m => Bool -> m ()
guard True = return ()
guard False = zero
module MonadPlus where
infixr 5 `plus`
class MonadPlus m where
plus :: m a -> m a -> m a
Wir haben damit außer dem bind (Kleisli-Komposition)
eine weitere Operation.
Damit wird aus dem Monoid sogar ein Ring.
Wir fordern
zero `plus` x = x = x `plus` zero x `plus` (y `plus z) = (x `plus` y) `plus` zOffensichtlich
module ListMonadPlus where import MonadZero import MonadPlus instance MonadZero [] where zero = [] instance MonadPlus [] where plus = (++)Aufgabe: erfüllt das nächste die beiden Axiome?
module MaybeMonadPlus where
import MonadZero
import MonadPlus
instance MonadZero Maybe where zero = Nothing
instance MonadPlus Maybe where
plus (Just x) y = Just x; plus Nothing y = y
Aufgabe: schreiben einige Axiome (Distributivgesetze)
für die vernünftige Zusammenarbeit von bind, zero und plus auf.
Prüfe die Gültigkeit für die beiden gegebenen Instanzen.
Die Klassen MonadZero, MonadPlus kann man selbst definieren, wie man will. Die gezeigte Variante war früher mal Standard. Im aktuellen Haskell98 sind die Klassen weiter verschmolzen. Schlecht für die Didaktik, angeblich gut für den Praktiker. Sehen Sie selbst in Prelude.hs und Monad.hs.