MonadPlusund Monoiddienen verschiedenen Zwecken.
A Monoidwird ü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 MonadPlusnicht nur gibt an, dass Sie eine monoidal Struktur, sondern auch , dass diese Struktur auf , wie die in Beziehung steht Monadfunktioniert, und dass diese Struktur nicht über den Wert schert in der Monade enthalten ist , das ist (teilweise ) , die durch die Tatsache , das MonadPlusbraucht 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 MonadPluseines oder beide dieser zusätzlichen Gesetze erfüllen.
Was ist also Alternative?
Applicativewurde nach definiert Monadund gehört logischerweise als Oberklasse von Monad, aber hauptsächlich aufgrund des unterschiedlichen Drucks auf die Designer in Haskell 98, Functorwar Monadbis 2015 nicht einmal eine Oberklasse von . Jetzt haben wir endlich Applicativeals Oberklasse von Monadin GHC (wenn nicht noch in einem Sprachstandard.)
Effektiv Alternativeist zu Applicativewas MonadPlusist zu Monad.
Für diese würden wir bekommen
empty <*> m = empty
analog zu dem, was wir haben MonadPlusund es gibt ähnliche Verteilungs- und Fangeigenschaften, von denen Sie mindestens eine erfüllen sollten.
Leider ist auch das empty <*> m = emptyRecht 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 fsowieso kein 'a' enthalten, um die Funktion aufzurufen.
Da jedoch Applicativeist nicht eine übergeordnete Klasse von Monadund Alternativeist nicht eine übergeordnete Klasse von MonadPlus, wickeln wir separat beiden Instanzen bis zu definieren.
Selbst wenn Applicativees eine Superklasse von wäre Monad, würden Sie die MonadPlusKlasse 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 MonadPlusist, ist stärker als die Behauptung, dass es ein ist Alternative.
Konventionell sollte das MonadPlusund Alternativefür einen bestimmten Typ übereinstimmen, aber das Monoidkann völlig anders sein.
Zum Beispiel das MonadPlusund Alternativefür Maybedas Offensichtliche tun:
instance MonadPlus Maybe where
mzero = Nothing
mplus (Just a) _ = Just a
mplus _ mb = mb
aber die MonoidInstanz hebt eine Halbgruppe in eine Monoid. Da es Semigroupzu 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 MonadPlusund AlternativeInstanzen für einen Typ in Beziehung gesetzt werden sollten, Monoidkann (und ist manchmal) etwas völlig anderes sein.
ApplicativeundMonadPlusscheinen genau gleich zu sein (Modulo-Superklassen-Einschränkungen).