MonadPlus
y Monoid
servent des objectifs différents.
A Monoid
est paramétrée sur un type de type *
.
class Monoid m where
mempty :: m
mappend :: m -> m -> m
et il peut donc être instancié pour presque tous les types pour lesquels il existe un opérateur évident qui est associatif et qui a une unité.
Cependant, MonadPlus
ne spécifie pas seulement que vous avez une structure monoïdale, mais aussi que cette structure est liée à la façon dont les Monad
travaux, y que cette structure ne se soucie pas de la valeur contenue dans la monade, ceci est (en partie) indiqué par le fait que MonadPlus
prend un argument de type * -> *
.
class Monad m => MonadPlus m where
mzero :: m a
mplus :: m a -> m a -> m a
En plus des lois du monoïde, nous avons deux ensembles potentiels de lois que nous pouvons appliquer à MonadPlus
. Malheureusement, la communauté n'est pas d'accord sur ce qu'ils devraient être.
Au moins, nous savons
mzero >>= k = mzero
mais il y a deux autres extensions concurrentes, la loi de distribution de gauche (sic)
mplus a b >>= k = mplus (a >>= k) (b >>= k)
et la loi de la prise à gauche
mplus (return a) b = return a
Ainsi, toute instance de MonadPlus
doit satisfaire à l'une ou aux deux lois supplémentaires.
Alors qu'en est-il Alternative
?
Applicative
a été défini après Monad
et appartient logiquement à une superclasse de Monad
mais en grande partie à cause des pressions différentes exercées sur les concepteurs à l'époque de Haskell 98, même Functor
n'était pas une superclasse de Monad
jusqu'en 2015. Maintenant, nous avons enfin Applicative
comme une superclasse de Monad
dans GHC (si ce n'est pas encore dans un standard de langage).
Efficacement, Alternative
est de Applicative
ce que MonadPlus
est de Monad
.
Pour ceux-ci, nous aurions
empty <*> m = empty
de manière analogue à ce que nous avons avec MonadPlus
et il existe des propriétés distributives et d'accrochage similaires, dont au moins une que vous devez satisfaire.
Malheureusement, même empty <*> m = empty
La loi est une affirmation trop forte. Elle ne tient pas pour À l'envers par exemple !
Lorsque nous regardons MonadPlus, la loi vide >>= f = vide nous est presque imposée. La construction vide ne peut pas contenir de 'a' pour appeler la fonction f
avec de toute façon.
Toutefois, étant donné que Applicative
es no une superclasse de Monad
y Alternative
es no une superclasse de MonadPlus
nous finissons par définir les deux instances séparément.
En outre, même si Applicative
était une superclasse de Monad
vous auriez besoin de la MonadPlus
de toute façon, parce que même si nous obéissions
empty <*> m = empty
ce n'est pas strictement suffisant pour prouver que
empty >>= f = empty
Donc, prétendre que quelque chose est MonadPlus
est plus fort que de prétendre que c'est Alternative
.
Maintenant, par convention, le MonadPlus
y Alternative
pour un type donné devraient concorder, mais les Monoid
peut être complètement différent.
Par exemple, le MonadPlus
y Alternative
para Maybe
faire la chose la plus évidente :
instance MonadPlus Maybe where
mzero = Nothing
mplus (Just a) _ = Just a
mplus _ mb = mb
mais le Monoid
L'instance transforme un semigroupe en un Monoid
. Malheureusement, parce qu'il n'existait pas de Semigroup
à l'époque en Haskell 98, elle le fait en exigeant une classe Monoid
mais sans utiliser son unité. _
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
est une affirmation plus forte que Alternative
qui, à son tour, est une affirmation plus forte que Monoid
et alors que le MonadPlus
y Alternative
les instances d'un type doivent être liées, la Monoid
peut être (et est parfois) quelque chose de complètement différent.
0 votes
C'est une bonne question. En particulier,
Applicative
yMonadPlus
semblent être exactement les mêmes (modulo les contraintes de superclasse).1 votes
Il y a aussi
ArrowZero
yArrowPlus
pour les flèches. Mon pari : rendre les signatures de type plus propres (ce qui rend les contraintes de superclasse différentes le site réelle différence).4 votes
@CatPlusPlus : bien,
ArrowZero
yArrowPlus
avoir une sorte* -> * -> *
ce qui signifie que vous pouvez les passer pour le type de flèche une seule fois pour une fonction qui doit les utiliser pour une multitude de types, pour utiliser uneMonoid
vous devez exiger une instance deMonoid
pour chaque instanciation particulière, et vous n'auriez aucune garantie qu'elles soient traitées de la même manière, les instances pourraient ne pas être liées !