MonadPlus
und Monoid
dienen verschiedenen Zwecken.
A Monoid
wird über eine Art von Art parametrisiert *
.
class Monoid m where
mempty :: m
mappend :: m -> m -> m
und so kann es für fast jeden Typ instanziiert werden, für den es einen offensichtlichen Operator gibt, der assoziativ ist und der eine Einheit hat.
Doch MonadPlus
nicht nur gibt an, dass Sie eine monoidal Struktur, sondern auch , dass diese Struktur auf , wie die in Beziehung steht Monad
funktioniert, und dass diese Struktur nicht über den Wert schert in der Monade enthalten ist , das ist (teilweise ) , die durch die Tatsache , das MonadPlus
braucht ein Argument der Art * -> *
.
class Monad m => MonadPlus m where
mzero :: m a
mplus :: m a -> m a -> m a
Zusätzlich zu den monoiden Gesetzen gibt es zwei mögliche Gesetze, auf die wir uns anwenden können MonadPlus
. Leider ist sich die Community nicht einig, was sie sein sollte.
Zumindest wissen wir es
mzero >>= k = mzero
Es gibt jedoch zwei weitere konkurrierende Erweiterungen, das linke (sic) Verteilungsgesetz
mplus a b >>= k = mplus (a >>= k) (b >>= k)
und das linke Fanggesetz
mplus (return a) b = return a
Daher sollte jeder Fall MonadPlus
eines oder beide dieser zusätzlichen Gesetze erfüllen.
Was ist also Alternative
?
Applicative
wurde nach definiert Monad
und gehört logischerweise als Oberklasse von Monad
, aber hauptsächlich aufgrund des unterschiedlichen Drucks auf die Designer in Haskell 98, Functor
war Monad
bis 2015 nicht einmal eine Oberklasse von . Jetzt haben wir endlich Applicative
als Oberklasse von Monad
in GHC (wenn nicht noch in einem Sprachstandard.)
Effektiv Alternative
ist zu Applicative
was MonadPlus
ist zu Monad
.
Für diese würden wir bekommen
empty <*> m = empty
analog zu dem, was wir haben MonadPlus
und es gibt ähnliche Verteilungs- und Fangeigenschaften, von denen Sie mindestens eine erfüllen sollten.
Leider ist auch das empty <*> m = empty
Recht ein zu starker Anspruch. Es gilt zum Beispiel nicht für Rückwärts !
Wenn wir uns MonadPlus ansehen, wird uns fast das leere >> = f = leere Gesetz aufgezwungen. Die leere Konstruktion kann f
sowieso kein 'a' enthalten, um die Funktion aufzurufen.
Da jedoch Applicative
ist nicht eine übergeordnete Klasse von Monad
und Alternative
ist nicht eine übergeordnete Klasse von MonadPlus
, wickeln wir separat beiden Instanzen bis zu definieren.
Selbst wenn Applicative
es eine Superklasse von wäre Monad
, würden Sie die MonadPlus
Klasse sowieso brauchen , denn selbst wenn wir gehorchen würden
empty <*> m = empty
das ist nicht streng genug, um das zu beweisen
empty >>= f = empty
Die Behauptung, dass etwas ein MonadPlus
ist, ist stärker als die Behauptung, dass es ein ist Alternative
.
Konventionell sollte das MonadPlus
und Alternative
für einen bestimmten Typ übereinstimmen, aber das Monoid
kann völlig anders sein.
Zum Beispiel das MonadPlus
und Alternative
für Maybe
das Offensichtliche tun:
instance MonadPlus Maybe where
mzero = Nothing
mplus (Just a) _ = Just a
mplus _ mb = mb
aber die Monoid
Instanz hebt eine Halbgruppe in eine Monoid
. Da es Semigroup
zu diesem Zeitpunkt in Haskell 98 noch keine Klasse gab, wird leider eine Klasse angefordert Monoid
, deren Einheit jedoch nicht verwendet. ಠ_ಠ
instance Monoid a => Monoid (Maybe a) where
mempty = Nothing
mappend (Just a) (Just b) = Just (mappend a b)
mappend Nothing x = x
mappend x Nothing = x
mappend Nothing Nothing = Nothing
TL; DR MonadPlus
ist eine stärkere Behauptung als Alternative
, was wiederum eine stärkere Behauptung ist als Monoid
, und während die MonadPlus
und Alternative
Instanzen für einen Typ in Beziehung gesetzt werden sollten, Monoid
kann (und ist manchmal) etwas völlig anderes sein.
Applicative
undMonadPlus
scheinen genau gleich zu sein (Modulo-Superklassen-Einschränkungen).