Какие проблемы программирования решают Monads? [закрыто]

14

Я прочитал много постов, которые объясняют, что такое монады, как unitи как bindработают, некоторые из них погружаются прямо в теорию категорий, настолько абстрактную (по крайней мере, для меня), что вызывает кровоточивость глаз, некоторые вообще игнорируют это и касаются странных аналогий буррито, ящики и что нет.

После нескольких недель обучения и большого количества жареных нейронов, (я думаю) я понимаю, как работают монады. Но есть еще одна вещь, которая ускользает от моего понимания, кое-что, о чем действительно касаются несколько постов (кроме IO и состояния):

ПОЧЕМУ?

Почему монады имеют значение? Почему они так важны? Какие проблемы они решают? Можно ли решить эти проблемы только с помощью монад или есть другие способы?

Пустышка я
источник
3
Программы большие и сложные. Нам нужны способы их структурирования. Есть много способов. Монады одно. Стрелки - это одно. Функторы едины. Объекты, Классы, Функции, Методы, Модули, Черты, Миксины, Пакеты, некоторые другие, На самом деле не совсем понятно, что именно вы задаете. Вы спрашиваете, почему мы должны структурировать программы?
Йорг Миттаг
1
@ JörgWMittag: Я НЕ спрашиваю, почему мы должны структурировать программы. Очевидно, что большая проблема разбита на более мелкие, которые вы можете решить, а затем объединить, чтобы получить решение для большой. Я спрашиваю, какие проблемы монады решают. Это оно? Структурирование кода? Это все суета? Например, в Haskell это то, как вы делаете ввод / вывод. Там монада - игра, изображающая из себя нечто чистое, хотя на самом деле это не так. Мой вопрос в названии, я не знаю, как это сформулировать более четко.
Dummy Me
2
Почему монады?
Роберт Харви
1
@RobertHarvey: я также нашел первые две ссылки, которые вы добавили, но, как и в ответах на эти и другие посты, ответы идут прямо на монады Maybe, State и IO, быстро переходят к примерам или коду и заканчиваются словами «там много проблем, которые можно решить с помощью монад ". Какие другие виды проблем? Я ищу ответ более высокого уровня, который вместо повторения одних и тех же примеров на самом деле идет к корню проблем (какими бы они ни были) и объясняет, как Монады решают их и почему это лучший выбор, а не использование чего-то еще. Большое спасибо за отзыв, хотя.
Dummy Me

Ответы:

10

Вам не нужны монады, чтобы что-то решить. Они просто делают некоторые вещи проще. Многие люди слишком абстрактны и теоретичны при объяснении монад. В основном, монады - это паттерн, который снова и снова появляется в программировании. Распознав этот шаблон, мы можем упростить наш код и избежать переопределения некоторых функций.

Для Хаскелла, с конкретной точки зрения, наиболее заметная вещь, которую позволяют монады, это делать нотацию . Постижения списков в Haskell и других языках также используют в своих интересах монады. Вы также можете создавать библиотеки, такие как Control.Monad .

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

Карл Билефельдт
источник
2
На самом деле, я бы сказал, что наиболее заметная вещь, которую позволяют монады haskell, - это простой способ получить эффекты ввода-вывода, которые действительно работают так, как вы ожидаете. Я думаю, что любой, кто интересуется, что дают нам монады, должен попробовать Миранду . Миранда - это язык, который Haskell был разработан для замены, и его должно быть очень легко выучить любому, имеющему опыт работы с Haskell. Основное отличие состоит в том, что он не имеет монадического ввода-вывода, что делает язык более сложным для работы, чем Haskell для любого нетривиального проекта.
Жюль
Да, IOэто самая выдающаяся монада Хаскелла , но я не приводил примеров отдельных монад. Я перечислял примеры всеобъемлющих абстракций, которые они позволяют. Я пытался понять, почему, например, первый парень, который подумает об использовании монады для IO, подумает, что это хорошая идея в целом.
Карл Билефельдт
1
@Jules: Или посмотрите историю Haskell. До Monads дизайнеры Haskell экспериментировали с Lazy Streams и Continuations в качестве основы для ввода / вывода, и оба были сложны в использовании.
Йорг Миттаг
5

Это легче понять, если вы посмотрите на конкретные монады и посмотрите, какие проблемы они решают. Например, в Haskell:

  • IO: Позволяет представлять IO в системе типов, поэтому вы можете очистить отдельные чистые функции от функций, выполняющих IO.

  • Список: Позволяет вам делать списки и нодерминистские вычисления.

  • Возможно: Лучшая альтернатива нулям и поддержка чего-то сравнимого с оператором ноль-слияния C #.

  • Parsec: удобный DSL для написания парсеров.

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

Могут ли приведенные выше примеры быть реализованы без монад? Конечно, они могут быть реализованы специальным образом, но наличие монад, встроенных в язык, обеспечивает прямую поддержку языка, например do-notation, которая работает со всеми монадами.

JacquesB
источник
2

Одна вещь, которая делает это запутанным, - то, что "популярные" функции как bindи <*>ориентированы на практику. Но чтобы понять концепции, проще сначала взглянуть на другие функции. Также стоит отметить, что монады выделяются, потому что они немного преувеличены по сравнению с другими связанными понятиями. Поэтому я начну с функторов.

Функторы предлагают функцию (в нотации Haskell) fmap :: (Functor f) => (a -> b) -> f a -> f b. Другими словами, у вас есть контекст, в fкоторый вы можете поднять функцию. Как вы можете себе представить, почти все является функтором. Списки, Возможно, Либо, функции, ввод / вывод, кортежи, парсеры ... Каждый представляет контекст, в котором может появляться значение. Таким образом, вы можете написать чрезвычайно универсальные функции, которые работают практически в любом контексте, используя fmapили его встроенный вариант <$>.

Что еще вы хотите сделать с контекстами? Возможно, вы захотите объединить два контекста. Таким образом , вы можете получить обобщение zip :: [a] -> [b] -> [(a,b)], например , как это: pair :: (Monoidal f) => f a -> f b -> f (a,b).

Но потому , что это еще более полезным на практике, Haskell библиотеки вместо этого предлагают Applicative, который представляет собой комбинацию Functorи Monoidal, а также Unit, что только добавляет , что вы можете поместить значения «внутри» свой контекст с unit.

Вы можете написать чрезвычайно общие функции, просто указав эти три вещи в контексте, в котором вы работаете.

Monadэто просто еще одна вещь, которую вы можете заявить в дополнение к этому. Раньше я не упоминал о том, что у вас уже есть два способа объединить два контекста: вы можете не только создавать pairих, но и составлять их, например, иметь список списков. В контексте ввода-вывода примером может служить действие ввода-вывода, которое может читать другие действия ввода-вывода из файла, поэтому у вас будет тип FilePath -> IO (IO a). Как мы можем избавиться от этого стека, чтобы получить исполняемую функцию IO a? Вот где приходит Monads join, это позволяет нам комбинировать два сложенных контекста одного типа. То же самое касается парсеров, может быть и т. Д. И bindэто просто более практичный способ использованияjoin

Таким образом, монадический контекст должен предлагать только четыре вещи, и его можно использовать практически со всеми механизмами, разработанными для ввода-вывода, для синтаксических анализаторов, для сбоев и т. Д.

MarLinn
источник
1

Monads позволяет вам выражать различные не чистые вычисления, а также упрощать код

  • вычисление с учетом состояния (получить / установить состояние через монаду)
  • Ввод / вывод (ведение журнала, пользовательский интерфейс, файл или просто создать / использовать список X)
  • Также «нелинейный» поток управления (т.е. исключения, может быть и т. Д.)

И, что важно, без компромисса с чисто языковыми конструкциями и извлечения из него более чистого языка

Маке
источник
2
Верно - но это только часть того, для чего используются монады. Список пониманий или Maybeне связанных с чем-то внешним.
JacquesB
Было бы полезно, если downvoters объяснить, почему они это сделали. Я не вижу ничего плохого в этом ответе.
Жюль
@JacquesB они, однако, с состоянием.
Жюль
1
Типы Мира, Типы Уникальности, Линейные Типы позволяют вам делать то же самое.
Йорг Миттаг
@Jules Списки как монада недетерминированности с состоянием? Не могли бы вы уточнить, каково ваше определение термина «с состоянием»?
Джек,