haskell monads monoids

haskell - ¿Por qué MonadPlus y no Monad+Monoid?



monads monoids (2)

Estoy tratando de entender la motivación detrás de MonadPlus . ¿Por qué es necesario si ya existen las clases de tipos Monad y Monoid ?

De acuerdo, las instancias de Monoid son tipos concretos, mientras que las instancias de Monad requieren un solo parámetro de tipo. (Consulte Monoid vs MonadPlus para obtener una explicación útil). ¿Pero no podría reescribir cualquier restricción de tipo de

(MonadPlus m) => ...

como una combinación de Monad y Monoid ?

(Monad m, Monoid (m a)) => ...

Tome la función de guard de Control.Monad , por ejemplo. Su implementación es:

guard :: (MonadPlus m) => Bool -> m () guard True = return () guard False = mzero

Pude implementarlo usando solo Monad y Monoid :

guard'' :: (Monad m, Monoid (m ())) => Bool -> m () guard'' True = return () guard'' False = mempty

¿Podría alguien aclarar la diferencia real entre MonadPlus y MonadPlus + Monoid ?


¿Pero no podrías reescribir cualquier restricción de tipo de

(MonadPlus m) => ...

como una combinación de Monad y Monoid?

No. En la respuesta superior a la pregunta que enlaza, ya hay una buena explicación sobre las leyes de MonadPlus vs. Monoid. Pero existen diferencias incluso si ignoramos las leyes de clases de tipos.

Monoid (ma) => ... significa que ma debe ser un monoide para un particular elegido por el que llama, pero MonadPlus m significa que ma debe ser un monoide para todo a . Entonces, MonadPlus a es más flexible y esta flexibilidad es útil en cuatro situaciones:

  1. Si no queremos decirle a la persona que llama qué intentamos usar.
    MonadPlus m => ... lugar de Monoid (m SecretType) => ...

  2. Si queremos usar múltiples diferentes a .
    MonadPlus m => ... lugar de (Monoid (m Type1), Monoid (m Type2), ...) => ...

  3. Si queremos usar infinitamente muchos diferentes a .
    MonadPlus m => ... lugar de no es posible.

  4. Si no sabemos lo que necesitamos. MonadPlus m => ... lugar de no es posible.


Tu guard'' no coincide con tu tipo de Monoid ma .

Si te refieres a Monoid (ma) , entonces necesitas definir qué es mempty para m () . Una vez que haya hecho eso, habrá definido un MonadPlus .

En otras palabras, MonadPlus define dos mzero : mzero y mplus cumplen dos reglas: mzero es neutral con respecto a mplus , y mplus es asociativo. Esto satisface la definición de mzero para que mzero sea mempty y mplus sea mappend .

La diferencia es que MonadPlus m es un MonadPlus m ma para cualquier a , pero Monoid m define un monoide solo para m . Tu guard'' funciona porque solo necesitas que m sea ​​un Monoid solo para () . Pero MonadPlus es más fuerte, afirma que ma es un monoide para cualquier a .