Вопрос по haskell – Различие между классами типов MonadPlus, Alternative и Monoid?

78

Стандартные библиотеки классов типов HaskellMonadPlus, Alternative, а такжеMonoid каждый из них предоставляет два метода с практически одинаковой семантикой:

An empty value: mzero, empty, or mempty. An operator a -> a -> a that joins values in the typeclass together: mplus, <|>, or mappend.

Все три определяют эти законы, которым должны придерживаться экземпляры:

<code>mempty `mappend` x = x
x `mappend` mempty = x
</code>

Таким образом, кажется, что все три типа классов обеспечиваютsame методы.

(Alternative также обеспечиваетsome а такжеmany, но их стандартных определений обычно достаточно, и поэтому они не слишком важны с точки зрения этого вопроса.)

Итак, мой вопрос: почему эти три чрезвычайно похожих класса? Есть ли какая-то реальная разница между ними, помимо их ограничений суперкласса?

Там такжеArrowZero а такжеArrowPlus для стрел. Моя ставка: сделать сигнатуры типов чище (что накладывает разные ограничения на суперклассthe реальная разница). Cat Plus Plus
Это хороший вопрос. Особенно,Applicative а такжеMonadPlus похожеexactly то же самое (ограничения по модулю суперкласса). Peter
@CatPlusPlus: хорошо,ArrowZero а такжеArrowPlus иметь вид* -> * -> *Это означает, что вы можете передать их для типа стрелки один раз для функции, которая должна использовать их для множества типов, чтобы использоватьMonoid Вы должны потребовать экземплярMonoid для каждого конкретного экземпляра, и вы не можете гарантировать, что с ними обращались подобным образом, экземпляры могут быть не связаны! Edward KMETT

Ваш Ответ

1   ответ
105

MonadPlus and Monoid serve different purposes.

Monoid параметризован по типу вида*.

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

и поэтому он может быть создан почти для любого типа, для которого существует очевидный оператор, который является ассоциативным и который имеет единицу.

Тем не мение,MonadPlus не только указывает, что у вас есть моноидальная структура, но и что эта структура связана с тем, какMonad работает,and что эта структура не заботится о значении, содержащемся в монаде, на это (частично) указывает тот факт, чтоMonadPlus принимает аргумент типа* -> *.

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

В дополнение к моноидным законам у нас есть два возможных набора законов, к которым мы можем применитьMonadPlus, К сожалению, сообщество не согласно с тем, что они должны быть.

По крайней мере, мы знаем

mzero >>= k = mzero

но есть два других конкурирующих расширения, левый (sic) закон распределения

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

и левый улов закон

mplus (return a) b = return a

Так что любой случайMonadPlus должен удовлетворять одному или обоим из этих дополнительных законов.

So what about Alternative?

Applicative был определен послеMonadи логически принадлежит как суперклассMonad, но в значительной степени из-за разного давления на дизайнеров в Haskell 98, дажеFunctor не был суперклассомMonad до 2015 года. Теперь у нас наконец естьApplicative как суперклассMonad в GHC (если еще не в стандарте языка.)

Эффективно,Alternative это кApplicative какиеMonadPlus это кMonad.

За это мы получим

empty <*> m = empty

аналогично тому, что мы имеем сMonadPlus и существуют аналогичные свойства дистрибутива и catch, по крайней мере одно из которых вы должны удовлетворить.

К сожалению дажеempty <*> m = empty закон слишком сильное требование. Это не относится кзадом, например!

Когда мы смотрим на MonadPlus, пустой закон & gt; & gt; = f = пустой закон почти навязывается нам. Пустая конструкция не может иметь каких-либо элементов для вызова функции.f с в любом случае.

Тем не менее, так какApplicative являетсяnot суперклассMonad а такжеAlternative являетсяnot суперклассMonadPlusмы определяем оба экземпляра отдельно.

Более того, даже еслиApplicative был суперклассомMonadВы должны получитьMonadPlus класс в любом случае, потому что даже если бы мы повиновались

empty <*> m = empty

этого недостаточно, чтобы доказать, что

empty >>= f = empty

Так утверждая, что что-тоMonadPlus сильнее, чем утверждать, что этоAlternative.

Теперь, по соглашению,MonadPlus а такжеAlternative для данного типа следует согласиться, ноMonoid может бытьcompletely разные.

Например,MonadPlus а такжеAlternative заMaybe сделать очевидную вещь:

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

ноMonoid Экземпляр поднимает полугруппу вMonoid, К сожалению, потому что не былоSemigroup класс в то время в Haskell 98, он делает это, требуяMonoid, но не используя свой блок. & # XCA0; _ & # xCA0;

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 это более сильное требование, чемAlternativeчто, в свою очередь, является более сильным требованием, чемMonoidи покаMonadPlus а такжеAlternative экземпляры для типа должны быть связаны,Monoid может быть (а иногда и есть) что-то совершенно другое.

Error: User Rate Limit ExceededMonadPlusError: User Rate Limit Exceeded
Error: User Rate Limit Exceededdifferent MonadPlusError: User Rate Limit ExceededAlternativeError: User Rate Limit Exceeded
Error: User Rate Limit Exceededmempty `mappend` x ≡ x.
Error: User Rate Limit ExceededMonadError: User Rate Limit ExceededAlternativeError: User Rate Limit ExceededMonadPlusError: User Rate Limit Exceededasked a questionError: User Rate Limit Exceeded
Error: User Rate Limit Exceeded

Похожие вопросы