Объяснение законов монады

Я получал то же сообщение об ошибке. Проблема возникла только тогда, когда Flash сделал вызов ExternalInterface, который был возвращен после сбоя Flash (по какой причине вообще). Исправление, которое я реализовал, было: Проверьте, все еще запущен и запущен Flash-объект, и если обратный вызов все еще является функцией этого объекта.

33
задан Matthias Braun 23 April 2018 в 13:54
поделиться

4 ответа

Ваши описания кажутся довольно хорошими. Обычно люди говорят о трех законах монады, которые у вас обозначены как 1, 2 и 4. Ваш третий закон немного отличается, и я перейду к нему позже.

Для трех законов монады я нахожу, что гораздо легче получить интуитивное понимание того, что они означают, когда они переписаны с использованием композиции Клейсли:

-- defined in Control.Monad
(>=>) :: Monad m => (a -> m b) -> (b -> m c) -> a -> m c
mf >=> n = \x -> mf x >>= n

Теперь законы можно записать так:

1) return >=> mf = mf                  -- left identity
2) mf >=> return = mf                  -- right identity
4) (f >=> g) >=> h = f >=> (g >=> h)   -- associativity

1) Левый закон идентичности - возврат значения не изменяет значение и ничего не делает в монаде.

2) Закон правого тождества - возвращение значения не изменяет значение и ничего не делает в монаде.

4) Ассоциативность - композиция монад ассоциативна (мне нравится ответ KennyTM)

Эти два закона тождества в основном говорят об одном и том же, но они оба необходимы, потому что return должен иметь идентичное поведение с обеих сторон оператора bind.

Теперь о третьем законе. Этот закон по сути говорит, что и экземпляр Functor, и ваш экземпляр Monad ведут себя одинаково, когда поднимают функцию в монаду, и что ни один из них не делает ничего монадического. Если я не ошибаюсь, то когда монада подчиняется трем другим законам, а экземпляр Functor подчиняется законам functor, то это утверждение всегда будет истинным.

Многое из этого взято из Haskell Wiki. Typeclassopedia также является хорошим справочником.

45
ответ дан 27 November 2019 в 17:48
поделиться

С другими ответами не спорю, но, возможно, стоит подумать о том, что законы монады на самом деле описывают два набора свойств. Как говорит Джон, третий закон, который вы упоминаете, немного отличается, но вот как можно разделить остальные:

Функции, которые вы связываете с монадой, компонуются так же, как обычные функции.

Как и в ответе Джона, то, что называется стрелкой Клейсли для монады - это функция с типом a -> m b. Считайте return как id, а (<=<) как (.), а законы монады - это их переводы:

  1. id . f эквивалентен f
  2. f . id эквивалентен f
  3. (f . g) . h эквивалентен f . (g . h)

Последовательности монадических эффектов складываются подобно спискам.

По большей части, вы можете думать о дополнительной монадической структуре как о последовательности дополнительных действий, связанных с монадическим значением; например, Maybe - это "сдаться" для Nothing и "продолжать" для Just. Комбинация двух монадических действий, таким образом, по существу объединяет последовательности поведения, которые они имели.

В этом смысле return снова является тождеством - нулевым действием, подобным пустому списку поведений - а (>=>) является конкатенацией. Таким образом, законы монад являются их переводами:

  1. [] ++ xs эквивалентен xs
  2. xs ++ [] эквивалентен xs
  3. (xs ++ ys) ++ zs эквивалентен xs ++ (ys ++ zs)

Эти три закона описывают до смешного общий паттерн, который Haskell, к сожалению, не может выразить в полной общности. Если вам интересно, Control.Category дает обобщение "вещей, которые выглядят как композиция функций", а Data.Monoid обобщает последний случай, когда не задействованы параметры типа.

22
ответ дан 27 November 2019 в 17:48
поделиться

Первые три закона гласят, что «return» только обертывает значение и больше ничего не делает. Таким образом, вы можете исключить «обратные» вызовы без изменения семантики.

Последний закон - ассоциативность для связывания. Это означает, что вы берете что-то вроде:

do
   x <- foo
   bar x
   z <- baz

и превращаете его в

do
   do
      x <- foo
      bar x
   z <- baz

, не меняя значения. Конечно, вы бы точно этого не сделали, но вы можете поместить внутреннее предложение do в оператор if и захотеть, чтобы оно означало то же самое, когда «if» истинно.

Иногда монады не подчиняются в точности этим законам, особенно когда возникает какое-то нижнее значение. Это нормально, если оно задокументировано и является «морально правильным» (то есть соблюдаются законы для не нижних значений, или результаты считаются эквивалентными каким-либо другим образом).

4
ответ дан 27 November 2019 в 17:48
поделиться

В терминах нотации do правило 4 означает, что мы можем добавить дополнительный блок do для группировки последовательности монадических операции.

    do                          do
                                  y <- do
      x <- m                             x <- m
      y <- k x          <=>              k x
      h y                         h y

Это позволяет функциям, возвращающим монадическое значение, работать правильно.

12
ответ дан 27 November 2019 в 17:48
поделиться