semigrupos semigrupo resueltos operacion monoides matematica ley interna grupo estructuras ejercicios discreta composicion binaria algebraicas abeliano haskell functional-programming typeclass applicative monoids

haskell - semigrupo - Distinción entre las clases de tipos MonadPlus, Alternativa y Monoide?



semigrupo matematica discreta (1)

MonadPlus y MonadPlus tienen diferentes propósitos.

Un Monoid se parametriza sobre un tipo de clase * .

class Monoid m where mempty :: m mappend :: m -> m -> m

y entonces puede ser instanciado para casi cualquier tipo para el cual haya un operador obvio que sea asociativo y que tenga una unidad.

Sin embargo, MonadPlus no solo especifica que tienes una estructura monoidal, sino también que esa estructura está relacionada con el funcionamiento de la Monad , y que a esa estructura no le importa el valor contenido en la mónada, esto (en parte) se indica mediante el hecho de que MonadPlus toma un argumento de tipo * -> * .

class Monad m => MonadPlus m where mzero :: m a mplus :: m a -> m a -> m a

Además de las leyes de monoid, tenemos dos posibles conjuntos de leyes que podemos aplicar a MonadPlus . Lamentablemente, la comunidad no está de acuerdo con lo que deberían ser.

Por lo menos, sabemos

mzero >>= k = mzero

pero hay otras dos extensiones en competencia, la ley de distribución de la izquierda (sic)

mplus a b >>= k = mplus (a >>= k) (b >>= k)

y la ley de captura a la izquierda

mplus (return a) b = return a

Entonces cualquier instancia de MonadPlus debería satisfacer una o ambas de estas leyes adicionales.

Entonces, ¿qué pasa con Alternative ?

Applicative fue definido después de Monad , y lógicamente pertenece como una superclase de Monad , pero en gran parte debido a las diferentes presiones sobre los diseñadores en Haskell 98, incluso Functor no era una superclase de Monad hasta 2015. Ahora finalmente tenemos Applicative como una superclase de Monad en GHC (si aún no está en un estándar de idioma)

Efectivamente, la Alternative es Applicative lo que MonadPlus es para MonadPlus .

Para estos, obtendríamos

empty <*> m = empty

de forma análoga a lo que tenemos con MonadPlus y existen propiedades distributivas y de captura similares, al menos una de las cuales debe satisfacer.

Desafortunadamente, incluso la empty <*> m = empty ley empty <*> m = empty es un reclamo demasiado fuerte. ¡No sirve para Backwards , por ejemplo!

Cuando miramos a MonadPlus, la ley vacía >> = f = empty casi nos es forzada. La construcción vacía no puede tener ninguna ''a'' para llamar a la función f de todos modos.

Sin embargo, dado que Applicative no es una superclase de Monad y Alternative no es una superclase de MonadPlus , terminaremos definiendo ambas instancias por separado.

Además, incluso si Applicative fuera una superclase de Monad , terminarías necesitando la clase MonadPlus todos modos, porque incluso si MonadPlus

empty <*> m = empty

eso no es estrictamente suficiente para demostrar que

empty >>= f = empty

Entonces, afirmar que algo es un MonadPlus es más fuerte que afirmar que es Alternative .

Ahora, por convención, el MonadPlus y la Alternative para un tipo dado deberían estar de acuerdo, pero el Monoid puede ser completamente diferente.

Por ejemplo, MonadPlus y Alternative for Maybe hacen lo obvio:

instance MonadPlus Maybe where mzero = Nothing mplus (Just a) _ = Just a mplus _ mb = mb

pero la instancia de Monoid levanta un semigroup en un Monoid . Tristemente porque no existía una clase Semigroup en ese momento en Haskell 98, lo hace al requerir un Monoid, pero sin usar su unidad. ಠ_ಠ

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 es una afirmación más sólida que Alternative , que a su vez es una afirmación más sólida que Monoid , y si bien las instancias MonadPlus y Alternative para un tipo deberían estar relacionadas, el Monoid puede ser (y algunas veces es) algo completamente diferente.

Las clases de MonadPlus Haskell de biblioteca estándar MonadPlus , Alternative y Monoid proporcionan dos métodos con esencialmente la misma semántica:

  • Un valor vacío: mzero , empty o mempty .
  • Un operador a -> a -> a que une los valores en la clase de tipos juntos: mplus , <|> o mappend .

Los tres especifican estas leyes a las cuales deben adherirse las instancias:

mempty `mappend` x = x x `mappend` mempty = x

Por lo tanto, parece que las tres clases de tipos proporcionan los mismos métodos.

(La Alternative también proporciona some y many , pero sus definiciones predeterminadas suelen ser suficientes, por lo que no son demasiado importantes en términos de esta pregunta).

Entonces, mi pregunta es: ¿por qué estas tres clases extremadamente similares? ¿Hay alguna diferencia real entre ellos, además de sus diferentes restricciones de superclase?