Монады и Стрелки


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

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

когда я должен использовать монады и когда я должен использовать стрелки?

2 65

2 ответа:

есть две отличные работы Линдли, Уодлера и Яллопа (обсуждается в LTU здесь).

самое главное, чтобы понять, что есть больше вещи, которые являются стрелами, чем есть вещи, которые являются монадами. И наоборот, монады строго сильнее стрел (второй документ выше точно указывает, каким образом).

в частности, монады-это стрелки, оснащенные функцией apply типа (a ~> b, a) ~> b, где (~>) является конструктором для данной стрелки. Lindley et al. обратите внимание, что это разрушает тщательное различие, которое стрелки поддерживают между терминами и командами (или, если вы предпочитаете, объектами и морфизмами).

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

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

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


вышеизложенное попыталось быть общим и описательным. Ниже приведены некоторые из моих самоуверенных правил большой палец.

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

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

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

там конечно, гораздо больше к истории. Для прозрачна, см. работа Конэла Эллиота над FRP в частности. Для стрелок, см. HXT XML parser library на проект YAMPA FRP на Haskell on a Horse web framework, Худак и Лю классический "затыкание утечки пространства стрелкой" бумага, между прочим. Для монад, смотрите везде. И, конечно, обратите внимание, что только потому, что что-то является монадой, это не означает, что аппликативная нотация не может быть более ясной и выразительной.

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

ответ "живописный маршрут"следует.

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

сейчас я выделю основные моменты из этих статей, которые относятся к вашему вопросу

когда монады были введены, люди думали, что они всемогущи. Действительно, монады обладают большой силой. Но у некоторых дело в том, что было обнаружено, что есть случаи, когда монады не могут быть применены. Эти случаи связаны с несколькими входами, особенно когда некоторые входы являются статическими, а некоторые-динамическими. Итак, Джон Хьюз подошел и представил стрелы.

стрелки более общие, чем монады. Стрелки-это надмножество монад. Они могут делать все, что делают монады, и даже больше. Но они также более сложны в использовании. Джон Хьюз рекомендует вам использовать монады всякий раз, когда вы можете и что вы следует использовать стрелки, когда вы не можете использовать монады.

Я согласен с Джоном Хьюзом. Мне также вспоминается цитата Эйнштейна: "Все должно быть сделано как можно проще, но не проще".

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

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

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

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

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