Различие между classами MonadPlus, Alternative и Monoid?

Стандартные библиотеки classов Haskell MonadPlus, Alternative и Monoid предоставляют два метода, по существу, одну и ту же семантику:

  • Пустое значение: mzero , empty или mempty .
  • Оператор a -> a -> a который объединяет значения в classе типов: mplus , или mappend .

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

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

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

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

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

MonadPlus и MonadPlus служат для разных целей.

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

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

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

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

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

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

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

 mzero >>= k = mzero 

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

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

и закон левого лова

 mplus (return a) b = return a 

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

Так что насчет Alternative ?

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

Фактически, Alternative – это MonadPlus то, что MonadPlus принадлежит MonadPlus .

Для этого мы получили бы

 empty <*> m = empty 

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

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

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

Однако, поскольку Applicative не является суперclassом Monad а Alternative не является суперclassом MonadPlus , мы MonadPlus определение обоих экземпляров отдельно.

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

 empty <*> m = empty 

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

 empty >>= f = empty 

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

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

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

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

но экземпляр Monoid поднимает полугруппу в Monoid . К сожалению, в то время, когда в Haskell 98 не существовал class Semigroup , он делает это, переставляя Monoid, но не используя его блок. ಠ_ಠ

 instance Monoid a => Monoid (Maybe a) where mempty = Nothing mappend (Just a) (Just b) = Just (mappend ab) mappend Nothing x = x mappend x Nothing = x mappend Nothing Nothing = Nothing 

TL; DR MonadPlus – более сильное требование, чем Alternative , которое, в свою очередь, является более сильным заявлением, чем Monoid , и в то время MonadPlus экземпляры MonadPlus и Alternative для типа должны быть связаны друг с другом, Monoid может быть (а иногда и есть) чем-то совершенно другим.

Давайте будем гением компьютера.