Как вы разрабатываете программы на Haskell или других функциональных языках программирования?

52

У меня есть некоторый опыт работы с объектно-ориентированными языками программирования, такими как c # или ruby. Я знаю, как проектировать программу в объектно-ориентированном стиле, как создавать классы и объекты и как определять отношения между ними. Я также знаю некоторые шаблоны дизайна.

Как люди пишут функциональные программы? Как они начинаются? Существуют ли шаблоны проектирования для функциональных языков? Применимы ли методологии, такие как экстремальное программирование или гибкая разработка, к функциональным языкам?

Люк
источник
1
связанный с этим вопрос: stackoverflow.com/questions/3077866/…
HaskellElephant

Ответы:

24

Я пишу свой ответ в основном с мыслью о Хаскеле, хотя многие концепции одинаково хорошо применимы и к другим функциональным языкам, таким как Erlang, Lisp (s) и ML. Некоторые даже применяются (в некоторой степени) к Ruby, Python, Perl и Javascript.

Как люди пишут функциональные программы? Как они начинаются?

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

Функциональное программирование очень хорошо подходит как для нисходящего, так и для восходящего подходов. Haskell настоятельно рекомендует писать ваши программы на языке высокого уровня, а затем просто определять детали вашего проекта высокого уровня. Смотрите minimum, например:

minimum    :: (Ord a) => [a] -> a
minimum xs =  foldl1 min xs

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

Существуют ли шаблоны проектирования для функциональных языков?

Есть две вещи, которые можно приравнять к «шаблонам проектирования», imho, функциям высшего порядка и монадам . Давайте поговорим о первом. Функции высшего порядка - это функции, которые либо принимают другие функции в качестве входных данных, либо создают функции в качестве выходных данных. Любой функциональный язык обычно делает интенсивное использование map, filterиfold(сворачивание часто также называют «уменьшить»): три очень основные функции высшего порядка, которые применяют функцию к списку различными способами. Они заменяют шаблон для петли красивым способом. Передача функций в качестве параметров является чрезвычайно мощным благом для программирования; Многие «шаблоны проектирования» можно выполнить проще, используя функции высшего порядка, возможность создавать свои собственные и использовать мощную стандартную библиотеку, которая полна полезных функций.

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

allPlus2 :: [Int] -> [Int]
allPlus2 xs = do x <- xs
                 return (x + 2)

Теперь, идиоматический способ сделать это на самом деле map, но ради иллюстрации, вы можете увидеть, как монада списка позволила мне написать функцию, которая выглядит так, как будто она работает с одним значением, но наделила ее сверхдержавой для работы с каждым элементом в список? Другие сверхдержавы включают отказ, состояние, взаимодействие с «внешним миром» и параллельное выполнение. Эти сверхспособности очень мощные, и большинство языков программирования позволяют функциям со сверхспособностями распространяться повсюду. Большинство людей говорят, что Haskell вообще не допускает этих сверхдержав, но на самом деле Haskell просто содержит их в монадах, поэтому их эффект можно ограничить и наблюдать.

Dr Grokking функции и монады высшего порядка - это эквивалент Хаскелла для шаблонов проектирования гроккинга. Как только вы изучите эти концепции Haskell, вы начнете думать, что «шаблоны проектирования» - это в основном дешевые обходные пути для имитации возможностей Haskell.

Применимы ли методологии, такие как экстремальное программирование или гибкая разработка, к функциональным языкам?

Я не вижу ничего, что связывало бы эти стратегии управления с какой-либо одной парадигмой программирования. Как сказал phynfo, функциональное программирование фактически вынуждает вас выполнять декомпозицию функций, разбивая большую проблему на подзадачи, поэтому мини-этапы должны быть простыми. Существуют такие инструменты, как QuickCheck и Zeno для тестирования или даже проверки свойств написанных вами функций.

Дэн Бертон
источник
«Я мог бы уточнить, но миру действительно не нужна еще одна аналогия с монадой». - Нам всегда нужно больше аналогий для монад, а ваша - одна из лучших, которые я видел.
Адам Гент
1
Отличный ответ, но я думаю, что ваше обсуждение шаблонов дизайна немного вводит в заблуждение. Хотя вам не нужны шаблоны проектирования в стиле OO / GOF в Haskell - на самом деле было бы нелепо пытаться их использовать - сами шаблоны - это просто способы, которыми сообщество передает решения для тех проблем, которые возникают снова и снова. Сообщество Haskell все еще очень молодо, поэтому пока не так много шаблонов, но если бы вы спросили меня о примерах шаблонов Haskell, я бы упомянул такие вещи, как GADT или Arrowized FRP.
rfperson