Объяснение комбинаторов для рабочего человека


что такое комбинатор??

это "функции или определение без свободных переменных" (как определено на SO)?

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

некоторые комбинаторы, соответствующие первому определению:

некоторые комбинаторы, которые соответствуют второй определение:

  • карта
  • фильтр
  • свернуть/уменьшить (предположительно)
  • любой из>>=, compose, fmap ?????

меня не интересует первое определение - это не поможет мне написать настоящую программу (+1, Если вы убедите меня, что я ошибаюсь). пожалуйста, помогите мне понять второе определение. Я думаю, что map, filter и reduce полезны: они позволяют мне программировать на более высоком уровне - меньше ошибок, короче и более четкий код. Вот некоторые из моих конкретных вопросов о комбинаторах:

  1. каковы еще примеры комбинаторов, таких как карта, фильтр?
  2. какие комбинаторы часто реализуют языки программирования?
  3. как комбинаторы могут помочь мне разработать лучший API?
  4. как я могу проектировать эффективные комбинаторы?
  5. какие комбинаторы похожи на нефункциональный язык (скажем, Java), или что эти языки используют в место комбинаторов?

обновление

благодаря @C. A. McCann, теперь у меня есть несколько лучшее понимание комбинаторов. Но один вопрос по-прежнему является для меня камнем преткновения:

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

Я подозреваю, что ответ заключается в том, что версия combinator-heavy короче, яснее, более общая, но я был бы признателен за более глубокое обсуждение, если это возможно.

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

1 86

1 ответ:

меня не интересует первое определение - это не поможет мне написать настоящую программу (+1, Если вы убедите меня, что я ошибаюсь). Пожалуйста, помогите мне понять второе определение. Я думаю, что map, filter и reduce полезны: они позволяют мне программировать на более высоком уровне-меньше ошибок, более короткий и четкий код.

эти два определения в основном одно и то же. Первый основан на формальном определении и примеры, которые вы даете примитивный комбинаторы--самые малые строительные блоки возможные. Они могут помочь вам написать реальную программу, поскольку с их помощью вы можете построить более сложные комбинаторы. Подумайте о комбинаторах, таких как S и K, как машинный язык гипотетического "комбинаторного компьютера". Конечно, реальные компьютеры не работают таким образом, поэтому на практике вы обычно будете иметь операции более высокого уровня, реализованные за кулисами другими способами, но концептуальная основа по-прежнему является полезным инструментом для понимания смысл из этих операций более высокого уровня.

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

каковы еще примеры комбинаторов, таких как карта, фильтр?

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

какие комбинаторы часто реализуют языки программирования?

Это будет меняться совсем немного. Их относительно немного полностью общие комбинаторы-в основном примитивные, упомянутые выше-поэтому в большинстве случаев комбинаторы будут иметь некоторое представление о любых используемых структурах данных (даже если эти структуры данных построены из других комбинаторов в любом случае), и в этом случае обычно есть несколько "полностью общих" комбинаторов, а затем любые различные специализированные формы, которые кто-то решил предоставить. Есть смешное количество случаев, когда (соответственно обобщенные версии) map, fold и unfold достаточно делать почти все, что вы могли хотеть.

Как комбинаторы могут помочь мне разработать лучший API?

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

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

Как создать эффективные комбинаторы?

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

что такое комбинаторы, подобные в нефункциональном языке (скажем, Java), или что эти языки используют вместо комбинаторов?

Ахахахаха. Забавно, что вы должны спросить, потому что объекты действительно являются вещами более высокого порядка в первую очередь-у них есть некоторые данные, но они также несут вокруг кучу операций, и довольно много того, что составляет хороший дизайн ООП сводится к тому, что "объекты обычно должны действовать как комбинаторы, а не структуры данных".