Что такое монада в ФП, в категориальных терминах? - PullRequest
49 голосов
/ 22 ноября 2011

Каждый раз, когда кто-то обещает «объяснить монады», мой интерес вспыхивает, и его заменяет разочарование, когда якобы «объяснение» представляет собой длинный список примеров, которые заканчиваются неявным замечанием, что «математическая теория» стоит«эзотерические идеи» «слишком сложны, чтобы объяснить их на данном этапе».

Теперь я прошу об обратном.Я хорошо разбираюсь в теории категорий, и я не боюсь погони за диаграммами, леммы Йонеды или производных функторов (да и вообще на монадах и дополнениях в категориальном смысле).дайте мне ясное и краткое определение того, что такое монада в функциональном программировании?Чем меньше примеров, тем лучше: иногда одно ясное понятие говорит о более чем ста робких примерах.Haskell прекрасно подходит для демонстрации, хотя я не привередлив.

Ответы [ 8 ]

31 голосов
/ 22 ноября 2011

На этот вопрос есть несколько хороших ответов: Монады как дополнения

Более конкретно, статья Дерека Элкинса "Вычисление монад с помощью теории категорий" в TMR # 13 должна иметь видконструкции, которые вы ищете: http://www.haskell.org/wikiupload/8/85/TMR-Issue13.pdf

Наконец, и, возможно, это действительно самое близкое к тому, что вы ищете, вы можете перейти прямо к источнику и взглянуть на основополагающие документы Могги по этой теме от1988-91: http://www.disi.unige.it/person/MoggiE/publications.html

См., В частности, "Понятия вычислений и монад".


Мои собственные, я уверен, слишком сжатые / неточные данные:

Начните с категории Hask, чьи объекты являются типами Haskell, а морфизмы которых являются функциями.Функции также являются объектами в Hask, как и продукты.Итак, Hask декартово замкнуто.Теперь введите стрелку, отображающую каждый объект в Hask на MHask, который является подмножеством объектов в Hask.Единица измерения!Затем введите стрелку, отображающую каждую стрелку на Hask на стрелку на MHask.Это дает нам карту и делает MHask ковариантным эндофунктором.Теперь введите стрелку, отображающую каждый объект в MHask, который генерируется из объекта в MHask (через единицу измерения), в объект в MHask, который его генерирует.Присоединиться!И из этого, MHask является монадой (и точнее моноидальным эндофунктором).

Я уверен, что есть причина, по которой вышеперечисленное является недостатком, и именно поэтому я бы действительно направил вас, если вы ищете формализм, в частности, на газеты Могги.

17 голосов
/ 22 ноября 2011

В качестве дополнения к ответу Карла, монада в Хаскеле (теоретически) такова:

class Monad m where
  join :: m (m a) -> m a
  return :: a -> m a
  fmap :: (a -> b) -> m a -> m b

Обратите внимание, что «связать» (>>=) можно определить как

x >>= f = join (fmap f x)

Согласно Haskell Wiki

Монада в категории C является тройной ( F : C → C,η: Id F , μ: F F F )

... с некоторыми аксиомами.Для Haskell fmap, return и join совпадают с F , η и μ соответственно.(fmap в Haskell определяет Функтор).Если я не ошибаюсь, Scala называет их map, pure и join соответственно.(Scala вызывает bind "flatMap")

12 голосов
/ 22 ноября 2011

Хорошо, используя терминологию и примеры на Haskell ...

Монада в функциональном программировании - это составной шаблон для типов данных с видом * -> *.

class Monad (m :: * -> *) where
    return :: a -> m a
    (>>=)  :: m a -> (a -> m b) -> m b

(В Хаскелле есть нечто большее, чем класс, но это важные части.)

Тип данных является монадой, если он может реализовать этот интерфейс, удовлетворяя при этом трем условиям реализации. Это «законы монады», и я оставлю это для этих многословных объяснений для полного объяснения. Я суммирую законы так: «(>>= return) является тождественной функцией, а (>>=) является ассоциативным». Это действительно не более того, даже если это можно выразить более точно.

И это все это монада. Если вы можете реализовать этот интерфейс, сохранив эти поведенческие свойства, у вас есть монада.

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

Что менее очевидно, так это то, что, как бы ни был абстрактен интерфейс, он позволяет обобщенно моделировать любой шаблон потока управления независимо от фактической реализации монады. Вот почему пакет Control.Monad в библиотеке GHC base имеет такие комбинаторы, как when, forever и т. Д. И именно поэтому возможность явного абстрагирования над любой реализацией монады является мощной, особенно с поддержкой системы типов .

6 голосов
/ 22 ноября 2011

Вам следует прочитать статью Эугенио Могги «Понятия вычислений и монад», в которых объясняется предложенная тогда роль монад в структурировании денотационной семантики эффективных языков.

Также есть связанный вопрос:

Ссылки для изучения теории на чисто функциональных языках, таких как Haskell?

Поскольку вы не хотите махать рукой, вы должны читать научные статьи, а не ответы на форумах или учебные пособия..

5 голосов
/ 22 ноября 2011

Монада - это моноид в категории эндофункторов, в чем проблема? .

Помимо юмора, я лично считаю, что монады, поскольку они используются в Haskell и функциональном программировании, лучше поняты с точки зрения монады как интерфейс ( как в ответах Карла и Дэна), а не с точки зрения монад как термин из теории категорий . Я должен признаться, что я действительно усвоил всю монаду только тогда, когда мне пришлось использовать монадическую библиотеку из другого языка в реальном проекте.

Вы упоминаете, что вам не понравились все учебники "много примеров". Кто-нибудь когда-нибудь указывал вам на бумагу Неуклюжий отряд ? В монаде IO основное внимание уделяется мужчине, но введение дает хорошее техническое и историческое объяснение , почему концепция монады была принята Хаскеллом в первую очередь.

5 голосов
/ 22 ноября 2011

Я не знаю, о чем говорю, но вот мое мнение:

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

В действительности нотация делает это ясным: это в основном особый вид языка, основанного на выражениях, который позволяет вам определять, что происходит между выражениями.Это как если бы вы могли определить, как ";"работал в C-подобных языках.

В этом свете все монады, которые я использовал до сих пор, имеют смысл: State не влияет на значение, но обновляет второе значение, которое передается из вычисления ввычисления в фоновом режиме;Maybe закорачивает значение, если оно когда-либо встречает Nothing;List позволяет вам иметь переменное число значений, переданных через;IO позволяет безопасно передавать нечистые значения.Более специализированные монады, которые я использовал, такие как Gen и парсеры Parsec, также похожи.

Надеюсь, это ясное объяснение, которое не совсем не основано.

4 голосов
/ 07 июня 2012

Поскольку вы понимаете монады в теоретико-категоричном смысле, я интерпретирую ваш вопрос как о представлении монад в функциональном программировании.Таким образом, мой ответ избегает любого объяснения того, что такое монада , или какой-либо интуиции о ее значении или использовании.

Ответ : В Хаскеле монада представлена ​​на внутреннем языке для некоторой категории как (интернализованные) карты тройки Клейсли.

Объяснение: Трудно быть точным в отношении свойств "Hask категории", и эти свойства в значительной степени не имеют отношения к пониманию представления монад в Haskell.Вместо этого для этого обсуждения более полезно понимать Haskell как внутренний язык для некоторой категории C .Функции Haskell определяют морфизмы в C , а типы Haskell являются объектами в C , но особая категория, в которой эти определения сделаны, не важна.

Параметрические типы данных, напримерdata F a = ..., являются объектными сопоставлениями , например F : | C | -> | C |.

Обычное описаниемонада в Хаскеле находится в тройной Клейсли (или расширение Клейсли ):

class Monad m where
    return :: a -> m a
    (>>=) :: m a -> (a -> m b) -> m b

где:

  • m - это объектное отображение m :| C | -> | C |
  • return - это *Операция 1061 * unit на объектах
  • >>= (произносится Хаскеллерсом "bind") - это операция extension для морфизмов, но с заменой первых двух параметров (см. Обычную подпись)расширения (-)* : (a -> m b) -> m a -> m b)

(Эти карты сами по себе интернализованы как семейства морфизмов в C , что возможно сm :| C | -> | C |).

Примечание * Haskell do (если вы сталкивались с этим), следовательно, является внутренним языком для категорий Kleisli.

2 голосов
/ 22 ноября 2011

Страница wikibook на Haskell содержит хорошее базовое объяснение.

...