Увеличивает ли функциональное программирование «репрезентативный разрыв» между проблемами и решениями? [закрыто]

18

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

Кажется, что объектно-ориентированный дизайн очень хорошо позволяет нам моделировать проблему с точки зрения объектов, например, проблема системы регистрации университетских курсов может быть смоделирована с помощью Courseкласса, Studentкласса и т. Д. Затем, когда мы пишем решение в ОО-языке у нас есть схожие классы, которые получают обязанности, и это, как правило, полезно для проектирования, особенно для модульности кода. Если я передам эту проблему 10 независимым командам, которые решают ее методом ОО, обычно у 10 решений будут общие классы, относящиеся к проблеме. Когда вы начинаете связываться и взаимодействовать с этими классами, может быть много различий, поэтому не существует такого понятия, как «нулевой разрыв представления».

Мой опыт работы с функциональным программированием очень ограничен (нет реального использования, только программы типа Hello World). Я не вижу, как такие языки позволяют легко сопоставлять решения FP с проблемами (с небольшим разрывом представления), как это делают языки OO.

Я понимаю преимущества FP по сравнению с параллельным программированием. Но я что-то упускаю или FP не об уменьшении репрезентативного разрыва (облегчения понимания решений)?

Еще один способ задать вопрос: будет ли много общего у кода FP 10 различных команд, решающих одну и ту же реальную проблему?


Из Википедии по абстракции (информатика) (выделено мое):

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

Пробел в представлении может быть потенциально увеличен, потому что [некоторые] реальные проблемы не легко моделируются с помощью таких абстракций.


Еще один способ уменьшить разрыв в представлении состоит в том, чтобы проследить элементы решения до проблемы. Буквы 0's' и 's' 1в машинном коде очень сложно отследить, тогда как Studentкласс легко отследить. Не все ОО-классы легко отслеживаются в проблемном пространстве, но многие делают.

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


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

У ОО-дизайна есть уровни абстракции на уровне функций / классов / пакетов с инкапсуляцией (контроль доступа, скрытие информации) на каждом, что облегчает управление сложностью. Это элементы, которые позволяют легче перейти от проблемы к решению и обратно.


Многие ответы говорят о том, как анализ и проектирование выполняются в FP способом, аналогичным ОО, но пока никто не цитирует ничего высокого уровня (Пол привел некоторые интересные вещи, но это низкий уровень). Я вчера много гуглял и нашел интересную дискуссию. Следующее - от Рефакторинга Функциональных Программ Саймона Томпсона (2004) (выделено мной)

При проектировании объектно-ориентированной системы считается само собой разумеющимся, что проектирование будет предшествовать программированию. Проекты будут написаны с использованием системы, подобной UML, которая поддерживается такими инструментами, как Eclipse. Начинающие программисты могут хорошо изучить подход визуального дизайна, используя такие системы, как BlueJ. Работа над подобной методологией для функционального программирования описана в FAD: Функциональный анализ и проектирование , но мало другой работы существует. Там может быть несколько причин для этого.

  • Существующие функциональные программы имеют масштаб, который не требует проектирования. Многие функциональные программы невелики, но другие, такие как компилятор Glasgow Haskell, являются существенными.

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

  • Функциональные программы построены как развивающаяся серия прототипов.

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

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

Вот набор диаграмм, предложенных FAD:

  • диаграммы зависимости функций, которые представляют функцию с теми, которые она использует в своей реализации;
  • диаграмма зависимостей типов, которая предоставляет один и тот же сервис для типов; и,
  • Диаграммы зависимостей модулей, которые представляют взгляды на модульную архитектуру системы.

В разделе 5.1 тезиса ФАД приведено тематическое исследование, которое представляет собой систему для автоматизации производства данных, относящихся к футбольной (футбольной) лиге. Требования являются на 100% функциональными, например, ввод результатов футбола, создание таблиц лиги, таблиц оценок, таблиц посещаемости, перенос игроков между командами, обновление данных после получения новых результатов и т. Д. Никаких упоминаний о том, как FAD работает для решения нефункциональных требований, не задокументировано Помимо заявления о том, что «новые функциональные возможности должны быть разрешены с минимальными затратами», это практически невозможно протестировать.

К сожалению, кроме FAD, я не вижу никаких современных ссылок на языки моделирования (визуальные), которые предлагаются для FP. UML - это еще одна парадигма, поэтому мы должны забыть об этом.

Fuhrmanator
источник
1
Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
maple_shaft

Ответы:

20

Основные данные структурированы одинаково практически в любой парадигме. Вы будете иметь a Student, a Courseи т. Д., Будь то объект, структура, запись или что-то еще. Разница с ООП заключается не в том, как структурированы данные, а в том, как структурированы функции.

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

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

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

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

Карл Билефельдт
источник
5
@ BenAaronson проблема в моем опыте состоит в том, что затем любая функция, связанная со студентом, добавляется в класс Student, и его обязанности растут и растут до тех пор, пока вам не придется внедрять, StudentCourseFiltererчтобы все было под контролем
AlexFoxGill
3
@Den Гибридные подходы имеют свои достоинства. Однако это неправда, что различие искусственно. Scala пришлось пойти на множество компромиссов, чтобы соответствовать OOP и FP (менее мощный вывод типов - это одно. Сложность - другое: да, язык, который смешивает OOP и FP, имеет тенденцию быть более сложным - как в « сложном для использования». и понять "- чем один из его более чистых братьев на двух крайностях).
Андрес Ф.
3
@Den См. Также Эрик Мейер "Программирование " в основном функциональное "не работает" , что противоречит гибридному подходу и полной "фундаменталистской" FP.
Андрес Ф.
4
Боюсь, популярность, которую вы описываете, - случайность истории. Я использую Scala на работе, и это сложный зверь из-за того, как он пытается смешивать FP и ООП. Переход на настоящий язык FP, такой как Haskell, ощущается как глоток свежего воздуха - и я не говорю с академической точки зрения!
Андрес Ф.
3
@ Я не могу сказать, что делает любая из этих функций. Однако я могу сказать вам, что если первая функция в FP была сортировкой или фильтром, она называлась бы фильтром или сортировкой , а не func(так же, как вы ее назвали и IFilterт. Д.). В общем, в FP вы бы назвали это funcили fкогда либо, sortлибо filterявляется правильным выбором! Например, при написании функции высшего порядка, которая принимает funcв качестве параметра.
Андрес Ф.
10

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

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

Техническим языком, лежащим в основе функционального программирования, является математика . Соответственно, проблемы, которые наиболее подходят для решения с использованием функционального программирования, являются по существу математическими задачами. По математике я не имею в виду тот тип математики, который вы бы увидели в бизнес-решениях, например сложение и вычитание. Скорее, я говорю о том виде математики, который вы могли бы видеть в Math Overflow, или о типе математики, который вы могли бы видеть в поисковике Orbitz (он написан на Лиспе).

Эта ориентация имеет некоторые важные последствия для функциональных программистов, пытающихся решить реальные проблемы программирования:

  1. Функциональное программирование скорее декларативно, чем обязательно; это касается прежде всего того, чтобы сообщать компьютеру, что делать, а не как это делать.

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

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

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

  5. Поскольку все практическое программное обеспечение генерирует побочные эффекты (I / O), чисто функциональные языки программирования требуют механизма для создания этих побочных эффектов, оставаясь при этом математически чистыми (монады).

  6. Функциональные программы могут быть более легко доказаны благодаря их математической природе. Система типов Haskell может находить во время компиляции то, чего не может большинство языков OO.

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

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

Роберт Харви
источник
6
@thepacker: у вас есть состояние в функциональном программировании. Отличается только представление: в ООП вы используете изменяемые переменные, тогда как в функциональном программировании вы можете использовать бесконечные потоки состояний, которые создаются на лету, когда программа должна их проверять. К сожалению, состояние часто идентифицируется с изменяемыми переменными, как если бы изменяемые переменные были единственным способом представления состояния. Как следствие, многие считают, что язык программирования без изменяемых переменных не может моделировать состояние.
Джорджио
12
«Соответственно, проблемы, которые наиболее подходят для решения с использованием функционального программирования, по сути являются математическими задачами». Я не согласен с этим утверждением (см. Также мой предыдущий комментарий), по крайней мере, я не понимаю, почему оно должно быть правдой или что оно на самом деле означает. Вы можете рассматривать обход структуры каталогов как математическую задачу и реализовывать ее с помощью рекурсивной функции, но, поскольку клиент не видит исходный код, вы просто решаете практическую задачу, например, поиск файла где-то в файловой системе. Я считаю такое различие между математическими и нематематическими проблемами искусственными.
Джорджио
5
+1, но я не продан по пунктам 2 и 4. Я видел множество уроков и постов в Haskell, которые начинаются с решения проблемы сверху вниз, определения всех типов и операций, чтобы увидеть, как все это сочетается, пока оставляя каждое значение и определение функции неопределенным (хорошо, определенным для создания исключения). Мне кажется, что программисты на Haskell стремятся более тщательно смоделировать проблему, потому что они более склонны добавлять тривиальные типы ради семантики - например, добавляя SafeStringтип для представления строк, которые были экранированы в HTML - и, как правило, больше отслеживают последствия.
Довал
4
«Проблемы, которые наиболее подходят для решения с помощью функционального программирования, по сути, математические проблемы». Это просто неправда. Тот факт, что концепция монад происходит от теории категорий, также не означает, что математические задачи являются наиболее естественной / подходящей областью для функциональных языков. Все это означает, что код, написанный на строго типизированных функциональных языках, может быть описан, проанализирован и рассужден об использовании математики. Это мощная дополнительная функция, а не то, что мешает вам писать «Приключения Барби Хорс» на Хаскеле.
Брюс
6
@itsbruce Barbie Horse Adventures - это серьезная математическая симуляция высочайшего калибра, в которой пиджон использует FP в слишком сложных числовых проекциях, таких как матрицы, описывающие физическое мерцание волос Барби в течение дискретного периода в различных возможных условиях реального мира, которые убеждают людей в полностью отклонить это как не относящееся к их повседневной деловой проблеме кодирования.
Джимми Хоффа
7

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

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

ООП и ФП рассматривают данные и операции с двух разных точек зрения и обеспечивают разные компромиссы, как уже отмечал Роберт Харви.

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

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

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

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

Этот другой подход к расширению является одной из причин, почему ООП более подходит для определенных задач, когда набор операций меняется реже, чем набор типов данных, с которыми работают эти операции. Типичным примером являются ГПИ: у вас есть фиксированный набор операций , которые все виджеты должны реализовать ( paint, resize, move, и т.д.) , и набор виджетов , которые вы хотите расширить.

Таким образом, в соответствии с этим измерением, ООП и ФП являются всего лишь двумя особыми способами организации вашего кода. См. SICP , в частности, Раздел 2.4.3, Таблица 2.22 и параграф Передача сообщений .

Подводя итог: в ООП вы используете данные для организации операций, в ФП вы используете операции для организации данных. Каждый подход сильнее или слабее в зависимости от контекста. В общем, ни один из двух не имеет более высокого репрезентативного разрыва между проблемой и решением.

Джорджио
источник
1
На самом деле, шаблон посетителя (в ООП) дает вам ту же силу, что вы сказали для FP. Это позволяет добавлять новые операции, в то же время затрудняя добавление новых классов. Интересно, если вы можете сделать то же самое в FP (например, добавление новых форматов вместо операций).
Эйфорический
1
Сценарий обработки изображений не кажется лучшим примером. Конечно, вы конвертируете изображения в какой-то внутренний формат и обрабатываете их вместо написания отдельных реализаций всех ваших инструментов обработки изображений для каждого типа изображений?
Привет,
1
@ Джорджио, может быть, я не понимаю предполагаемого значения этой части: «добавление новых форматов требует больше усилий: вам нужно изменить все функции, которые вы уже реализовали».
Привет,
2
@ Эй, Джорджио, вероятно, имеет в виду так называемую проблему выражения . «Добавление новых форматов» означает «добавление новых конструкторов (« случаев ») к типу данных».
Андрес Ф.
1
@Euphoric: я не изучал детали, но аналог FP шаблону посетителя должен включать Otherвариант / конструктор в вашем типе данных и дополнительный параметр функции, который должен быть передан всем функциям для обработки другого случая. Это, конечно, неудобно / менее естественно в отношении решения ООП (динамическая диспетчеризация). Таким же образом, шаблон посетителя неуклюжий / менее естественный, чем решение FP (функция более высокого порядка).
Джорджио
5

Большинство функциональных языков не являются объектно-ориентированными. Это не означает, что у них нет объектов (в смысле сложных типов, с которыми связана определенная функциональность). В Haskell, как и в Java, есть списки, карты, массивы, всевозможные деревья и многие другие сложные типы. Если вы посмотрите на модуль Haskell List или Map, вы увидите набор функций, очень похожих на методы в большинстве эквивалентных модулей библиотеки OO-языка. Если вы проверяете код, вы даже найдете похожую инкапсуляцию с некоторыми типами (или, если быть точным, с их конструкторами) и функциями, которые могут использоваться только другими функциями в модуле.

То, как вы работаете с этими типами в Haskell, часто почти не отличается от способа OO. В Хаскеле я говорю

  null xs
  length xs

а на яве ты говоришь

  xs.isEmpty
  xs.length

Помидор, помидор. Функции Haskell не привязаны к объекту, но тесно связаны с его типом. «Ага, но , - говорите вы, - на Java вызывается метод, длина которого соответствует реальному классу этого объекта». Сюрприз - Haskell тоже делает полиморфизм с классами типов (и другими вещами).

В Haskell, если у меня есть - коллекция целых чисел - не имеет значения, является ли коллекция списком, множеством или массивом, этот код

  fmap (* 2) is

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

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

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

itsbruce
источник
На самом деле, вы можете использовать классы типов в Java / C #; Вы просто явно передаете словарь функций вместо того, чтобы компилятор выводил правильный, основанный на типе.
Довал
О, безусловно. Как сказал Уильям Кук, в ОО-коде на самом деле чаще используются функции более высокого порядка, чем в функциональном, хотя кодер, вероятно, не знает об этом.
Брюс
2
Вы делаете ложное различие. Список - это не более инертная структура данных, чем стек, очередь или симулятор крестики-нолики. Список может содержать что угодно (в Haskell это могут быть частично примененные функции) и определяет, как с этими вещами можно взаимодействовать. Вы можете применить список, полный частично примененных функций, к другому списку значений, и в результате вы получите новый список, содержащий все возможные комбинации функций из первой и входные данные со второй. Это гораздо больше, чем структура Си.
itbruce
3
Типы используются для более разнообразных вещей в функциональных языках, чем в императивных / OO (системы типов имеют тенденцию быть более мощными и последовательными, с одной стороны). Типы и их функции используются, например, для формирования путей кода (поэтому некоторые функциональные языки просто не имеют ключевых слов для циклов - не нужны).
Брюс
4
@Fuhrmanator «Я не вижу, как это делается в FP». Итак, вы жалуетесь на то, что не понимаете, не имеет смысла; иди изучи это, пойми это полностью, и тогда это будет иметь смысл. Возможно, после того, как в этом есть смысл, вы решите, что это дерьмо, и вам не нужны другие, чтобы доказать это вам, хотя другие люди, такие как выше, понимают это и не пришли к такому выводу. Вы, кажется, принесли нож в перестрелку, и теперь вы говорите всем, что оружие бесполезно, потому что оно не острое.
Джимми Хоффа
4

FP действительно стремится к сокращению репрезентативного разрыва:

Что-то, что вы увидите много на функциональных языках, - это практика построения языка (используя восходящий дизайн) в Embedded Domain Specific Language (EDSL) . Это позволяет вам разрабатывать средства выражения ваших деловых проблем естественным для вашего домена языком программирования. Хаскелл и Лисп оба гордятся этим.

Часть (если не все) того, что обеспечивает эту способность, заключается в большей гибкости и выразительности в самом базовом языке (ах); с функциями первого класса, функциями высшего порядка, композицией функций, а также в некоторых языках, алгебраическими типами данных (различаемые объединения AKA) и способностью определять операторы *, существует больше возможностей для выражения вещей, чем в OOP, который означает, что вы, вероятно, найдете более естественные способы выразить вещи из вашей проблемной области. (Следует сказать, что многие языки ООП в последнее время применяют многие из этих функций, если не начинать с них.)

* Да, во многих языках ООП вы можете переопределить стандартные операторы, но в Haskell вы можете определить новые!

В моем опыте работы с функциональными языками (в основном, F # и Haskell, немного Clojure и немного Lisp и Erlang) мне легче сопоставить проблемное пространство с языком, чем с OOP - особенно с алгебраическими типами данных, который я считаю более гибким, чем классы. Когда я начинал с FP, особенно с Haskell, меня бросило в тупик то, что я должен был думать / работать на более высоком уровне, чем я привык в императивных или ООП-языках; Вы можете столкнуться с этим немного.

Павел
источник
Деловые проблемы (от клиента) не очень часто выражаются в функциях более высокого порядка. Но клиент может написать однострочную историю пользователя и предоставить вам бизнес-правила (или вы можете получить их от клиента). Меня интересует (сверху вниз?) Моделирование предметной области (из этих артефактов), которая позволяет нам прийти к абстракциям проблемы, которые сопоставляются с первоклассными функциями и т. Д. Можете ли вы привести некоторые ссылки? Можете ли вы использовать конкретный пример домена, абстракций и т. Д.?
Фурманатор
3
@Fuhrmanator Клиент по-прежнему может писать однострочные пользовательские истории и бизнес-правила независимо от того, используете ли вы ООП и FP . Я не ожидаю, что клиенты поймут функции более высокого порядка, как я ожидаю, что они поймут наследование, структуру или интерфейсы.
Андрес Ф.
1
@Fuhrmanator Как часто заказчик выражал свою обеспокоенность в терминах обобщений Java или абстрактных базовых классов и интерфейсов? О, Боже. Пол дал вам очень хороший ответ, объяснив практический и надежный метод моделирования с использованием техник, которые, несомненно, не так сложно визуализировать. И все же вы настаиваете, чтобы это было описано в терминах одной конкретной методики моделирования для одной конкретной парадигмы, как если бы это был каким-то образом наиболее естественный способ представления дизайна, а все остальное можно перерисовать в его терминах.
Брюс
@Fuhrmanator Это может быть не так высокоуровнево, как вы ищете, но должно дать некоторое представление о процессе проектирования с использованием функциональных методов: Проектирование с использованием типов . Я бы порекомендовал просмотреть этот сайт в целом, потому что он имеет несколько отличных статей.
Павел
@Fuhrmanator Также есть серия « Мышление функционально »
Пол
3

Как сказал Никлаус Вирт, «Алгоритмы + структуры данных = программы». Функциональное программирование - это способ организации алгоритмов и мало что говорит о способах организации структур данных. Действительно, существуют языки FP как с изменяемыми (Lisp), так и с неизменяемыми (Haskell, Erlang) переменными. Если вы хотите сравнить и сопоставить FP с чем-то, вы должны выбрать императивное (C, Java) и декларативное (Prolog) программирование.

С другой стороны, ООП - это способ построения структур данных и привязывания к ним алгоритмов. FP не мешает вам создавать структуры данных, подобные ООП. Если вы мне не верите, взгляните на объявления типов в Haskell. Однако большинство языков FP согласны с тем, что функции не принадлежат структурам данных и должны находиться в одном и том же пространстве имен. Это сделано для того, чтобы упростить построение новых алгоритмов с помощью композиции функций. В самом деле, если вы знаете, какой ввод принимает функция и какой вывод она производит, почему это должно иметь значение, к какой структуре данных она тоже принадлежит? Например, почему addфункция должна вызываться для экземпляра типа Integer и передавать аргумент вместо простой передачи двух аргументов Integer?

Поэтому я не понимаю, почему FP должен усложнять понимание решений в целом, и я не думаю, что это так или иначе. Однако имейте в виду, что опытный императивный программист наверняка найдет функциональные программы сложнее для понимания, чем императивные, и наоборот. Это похоже на дихотомию Windows - Linux, когда люди, которые потратили 10 лет на то, чтобы освоить среду Windows, находят Linux трудным после месяца использования, а те, кто привык к Linux, не могут достичь той же производительности в Windows. Следовательно, «репрезентативный разрыв», о котором вы говорите, очень субъективен.

mkalkov
источник
Из-за инкапсуляции и сокрытия данных, которые сами по себе не являются принципами ОО, я не совсем согласен с тем, что ОО - это структуры данных + алгоритмы (это только внутреннее представление). Прелесть любой хорошей абстракции в том, что она предоставляет некоторые услуги для решения части проблемы, при этом не нужно понимать слишком много деталей. Я думаю, что вы говорите об инкапсуляции, когда вы разделяете функции и данные в FP, но я слишком зелен, чтобы знать наверняка. Кроме того, я отредактировал свой вопрос, чтобы сослаться на отслеживание от решения до проблемы (чтобы прояснить значение пробела в представлении).
Фурманатор
if you know what input a function takes and what output it produces, why should it matter which data structure it belongs too?Это очень похоже на сплоченность, что важно для любой модульной системы. Я бы сказал, что незнание того, где найти функцию, затруднит понимание решения, что связано с большим разрывом в представлении. Многие ОО-системы имеют эту проблему, но это из-за плохого дизайна (низкая когезия). Опять же, проблема пространства имен выходит за рамки моего опыта в FP, так что, возможно, это не так плохо, как кажется.
Фурманатор
1
@Fuhrmanator Но вы же знаете , где найти такую функцию. И для каждого типа данных определена только одна функция, а не несколько функций с одинаковыми именами (опять же, см. «Проблема выражения»). Например, для функций библиотеки Haskell (которые рекомендуется использовать вместо повторного открытия колеса или создания чуть менее полезных версий упомянутых функций) у вас есть замечательные инструменты обнаружения, такие как Hoogle , который настолько мощный, что позволяет искать по подписи (попробуйте! :))
Андрес Ф.
1
@Fuhrmanator, после «Это звучит очень похоже на сплоченность», я бы ожидал, что вы логически заключите, что языки FP позволяют вам писать программы с большей сплоченностью, но вы удивили меня. :-) Я думаю, вы должны выбрать язык FP, выучить его и решить для себя. Если бы я был вами, я бы предложил начать с Haskell, поскольку он достаточно чистый и поэтому не позволит вам писать код в императивном стиле. Erlang и некоторые Lisp также хороши, но они смешиваются в других стилях программирования. Scala и Clojure, IMO, довольно сложны для начала.
Мкалков