MonadPluse Monoidservem a diferentes propósitos.
A Monoidé parametrizado sobre um tipo de tipo *.
class Monoid m where
mempty :: m
mappend :: m -> m -> m
e, portanto, pode ser instanciado para quase qualquer tipo para o qual haja um operador óbvio que seja associativo e que tenha uma unidade.
No entanto, MonadPlusnão especifica apenas que você tem uma estrutura monoidal, mas também que essa estrutura está relacionada a como Monadfunciona, e que essa estrutura não se preocupa com o valor contido na mônada, isso é (em parte) indicado pelo fato isso MonadPlusleva um argumento do tipo * -> *.
class Monad m => MonadPlus m where
mzero :: m a
mplus :: m a -> m a -> m a
Além das leis monoidais, temos dois conjuntos potenciais de leis que podemos aplicar MonadPlus. Infelizmente, a comunidade discorda quanto ao que deveriam ser.
Pelo menos sabemos
mzero >>= k = mzero
mas há duas outras extensões concorrentes, a lei de distribuição de esquerda (sic)
mplus a b >>= k = mplus (a >>= k) (b >>= k)
e a esquerda pega a lei
mplus (return a) b = return a
Portanto, qualquer instância de MonadPlusdeve satisfazer uma ou ambas as leis adicionais.
Então sobre o quê Alternative?
Applicativefoi definido depois Monad, e logicamente pertence como uma superclasse de Monad, mas em grande parte devido às diferentes pressões sobre os designers em Haskell 98, ainda Functornão era uma superclasse de Monadaté 2015. Agora finalmente temos Applicativecomo uma superclasse de Monadem GHC (se não ainda em um padrão de idioma.)
Efetivamente, Alternativeé para o Applicativeque MonadPlusé Monad.
Para estes nós obteríamos
empty <*> m = empty
analogamente ao que temos com MonadPluse existem propriedades distributivas e de captura semelhantes, pelo menos uma das quais você deve satisfazer.
Infelizmente, mesmo a empty <*> m = emptylei é uma afirmação muito forte. Não vale para Backwards , por exemplo!
Quando olhamos para MonadPlus, a lei vazia >> = f = vazia é quase imposta a nós. A construção vazia não pode ter nenhum 'a's nela para chamar a função de fqualquer maneira.
No entanto, como nãoApplicative é uma superclasse de e não é uma superclasse de , acabamos definindo ambas as instâncias separadamente.MonadAlternativeMonadPlus
Além disso, mesmo se Applicativefosse uma superclasse de Monad, você acabaria precisando da MonadPlusclasse de qualquer maneira, porque mesmo se nós obedecêssemos
empty <*> m = empty
isso não é estritamente suficiente para provar que
empty >>= f = empty
Portanto, afirmar que algo é a MonadPlusé mais forte do que afirmar que é Alternative.
Agora, por convenção, o MonadPluse Alternativepara um determinado tipo devem concordar, mas o Monoidpode ser completamente diferente.
Por exemplo, o MonadPluse Alternativepara Maybefazem a coisa óbvia:
instance MonadPlus Maybe where
mzero = Nothing
mplus (Just a) _ = Just a
mplus _ mb = mb
mas a Monoidinstância eleva um semigrupo em a Monoid. Infelizmente, porque não existia uma Semigroupclasse na época em Haskell 98, ele faz isso solicitando a Monoid, mas não usando sua unidade. ಠ_ಠ
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 é uma afirmação mais forte do que Alternative, que por sua vez é uma afirmação mais forte do que Monoid, e embora as instâncias MonadPluse Alternativepara um tipo devam estar relacionadas, Monoidpode ser (e às vezes é) algo completamente diferente.
ApplicativeeMonadPlusparecem ser exatamente os mesmos (restrições da superclasse do módulo).