С первого дня моей карьеры программиста я начал с объектно-ориентированного программирования. Однако мне интересно изучать другие парадигмы (кое-что, о чем я говорил здесь на SO несколько раз, это хорошо, но у меня не было времени на это). Думаю, я не только готов, но и имею время, поэтому начну функциональное программирование с F#.
Однако я не уверен, как структурировать гораздо меньше дизайнерских приложений. Я привык к идеям «один класс на файл» и «класс существительное / функция-глагол» в объектно-ориентированном программировании. Как вы проектируете и структурируете функциональные приложения?





Учитывая, что современные функциональные языки (т.е. не шепелявые) по умолчанию используют полиморфные функции с ранней привязкой (эффективно), и что объектная ориентация - это просто особый способ организации полиморфных функций, на самом деле это не сильно отличается, если вы знаете, как проектировать правильно инкапсулированные классы.
Lisps использует позднее связывание для достижения аналогичного эффекта. Если честно, особой разницы нет, за исключением того, что вы явно не объявляете структуру типов.
Если вы много работали с шаблонными функциями C++, то, вероятно, у вас уже есть идея.
В любом случае ответ - небольшие «классы», и вместо изменения внутреннего состояния вы должны вернуть новую версию с другим состоянием.
Я не уверен, как можно применить полиморфизм к функциональному программированию.
Вы по-прежнему можете изменять структуры, и это разница, но процесс проектирования аналогичен. Основное отличие заключается в сосредоточении внимания на очень хорошо определенных интерфейсах с хорошим поведением, которые позволяют использовать, например, итерационные функции разумны. Эта привычка помогает сгладить структуру программы и ускоряет разработку.
@dacracot - прочтите этот en.wikipedia.org/wiki/Type_polymorphism, чтобы увидеть, как полиморфизм применяется к функциональному программированию
@jop - Вы можете псевдополиморфизировать данные с помощью преобразования (т.е. char как int), но приведение и полиморфизм подразумевают разные вещи. С полиморфизмом Cirle - это форма через наследование. С кастингом я действительно могу сказать, что char IS A int, просто я могу преобразовать char в int.
Дакракот, ты не знаешь, что такое полиморфизм. Полиморфизм в этом контексте - это способность передавать разные типы одной и той же функции. Это то, что вам дает и объектная ориентация.
Я бы добавил, что вы не читали статью, на которую ссылался Джоп.
@Marcin - Я понимаю вашу точку зрения, но спрашивающий ищет новую парадигму. Я подозреваю, что он имеет представление о том, что такое полиморфизм. Если ваше определение зависит от контекста, это только сбивает с толку. Это сделало меня.
Дакракот, это определение не зависит от контекста. Это определение также является определением полиморфизма, применимого к объектно-ориентированному программированию. Просто потому, что вы этого не понимаете, это не значит, что это неверно или вводит в заблуждение.
Также: Downvoters - не хотите ли прокомментировать, в чем ваша проблема с этим ответом?
Прочтите SICP.
Также доступен Версия PDF.
См. Заметки этого парня о SICP - очень подробные. eli.thegreenplace.net/category/programming/lisp/sicp
Также en.wikipedia.org/wiki/Functional_design
Незначительное обновление: заметки Эли теперь находятся на eli.thegreenplace.net/tag/sicp
Функциональное программирование - это определенно другая парадигма. Возможно, самый простой способ осознать это - настоять на том, чтобы дизайн был оформлен с помощью блок-схемы. Каждая функция отлична, без наследования, без полиморфизма, отличная. Данные передаются от функции к функции для удаления, обновления, вставки и создания новых данных.
Думаю, однажды об этом говорил один профессор ... что-то о том, чтобы копнуть все данные, чтобы создать что-то новое. Это то, что он имел в виду?
Я так считаю. Большой проблемой, которую функциональное программирование ставит перед разработчиком / дизайнером, является забота о больших двоичных объектах данных и их кормление. Он отдельный и является частью функций. Вы должны очень тщательно структурировать его, чтобы он был совместим со всеми функциями, которые вы хотите использовать.
Я бы не рекомендовал блок-схему совсем. Фактически, смысл функционального программирования заключается в том, что вы можете смоделировать набор функций как одну функцию, которая выполняет составное преобразование, которое они составляют.
-1 Функциональное программирование полно полиморфизма, гораздо больше, чем типичное ООП / императив.
Возможно, вы захотите проверить мою недавнюю запись в блоге: Как функциональное программирование влияет на структуру вашего кода?
На высоком уровне методология объектно-ориентированного проектирования по-прежнему весьма полезна для структурирования программы F#, но вы обнаружите, что это ломается (больше исключений из правила), когда вы спускаетесь на более низкие уровни. На физическом уровне «один класс на файл» не будет работать во всех случаях, так как взаимно рекурсивные типы должны быть определены в одном файле (тип Class1 = ... и Class2 = ...), и немного вашего код может находиться в «свободных» функциях, не связанных с конкретным классом (это то, для чего подходят «модули» F#). Ограничения порядка файлов в F# также заставят вас критически задуматься о зависимостях между типами в вашей программе; это палка о двух концах, так как может потребоваться больше работы / размышлений, чтобы распутать высокоуровневые зависимости, но в результате будут получены программы, которые организованы таким образом, чтобы всегда делать их доступными (поскольку самые примитивные сущности всегда на первом месте, и вы можете всегда читайте программу «сверху вниз» и вводите новые вещи один за другим, вместо того, чтобы просто искать каталог, полный файлов кода и не знать, «с чего начать»).
Как разрабатывать программы - все об этом (утомительно, используя Scheme вместо F#, но принципы сохраняются). Вкратце, ваш код отражает ваши типы данных; эта идея восходит к старомодному «структурированному программированию», только в функциональном программировании она более ясна и с более причудливыми типами данных.
F# предоставляет традиционные объектно-ориентированные подходы для крупномасштабного структурированного программирования (например, интерфейсы) и не пытается предоставить экспериментальные подходы, впервые реализованные в таких языках, как OCaml (например, функторы).
Следовательно, крупномасштабное структурирование программ на F# по сути такое же, как и в программах на C#.
По структурированию функциональных программ:
В то время как объектно-ориентированные языки структурируют код с помощью классов, функциональные языки структурируют его с помощью модулей. Объекты содержат состояние и методы, модули содержат типы данных и функции. В обоих случаях структурные единицы группируют типы данных вместе со связанным поведением. Обе парадигмы имеют инструменты для создания и обеспечения соблюдения барьеров абстракции.
Я настоятельно рекомендую выбрать удобный для вас язык функционального программирования (F#, OCaml, Haskell или Scheme) и внимательно изучить структуру его стандартной библиотеки.
Сравните, например, модуль OCaml Куча с System.Collections.Generic.Stack из .NET или аналогичной коллекцией на Java.
Объекты не обязательно содержат состояние. Посмотрите, например, обновление функционального объекта в OCaml.
Это все о чистых функциях и о том, как их скомпоновать для построения более крупных абстракций. На самом деле это сложная проблема, для которой требуется надежный математический фон. К счастью, есть несколько шаблонов, по которым доступны глубокие формальные и практические исследования. На Функциональное и реактивное моделирование предметной области Дебасиш Гхош подробнее исследует эту тему и объединяет несколько практических сценариев, применяющих чистые функциональные шаблоны:
Functional and Reactive Domain Modeling teaches you how to think of the domain model in terms of pure functions and how to compose them to build larger abstractions. You will start with the basics of functional programming and gradually progress to the advanced concepts and patterns that you need to know to implement complex domain models. The book demonstrates how advanced FP patterns like algebraic data types, typeclass based design, and isolation of side-effects can make your model compose for readability and verifiability.
Так что на самом деле это много одного и того же. Просто другой образ мышления. Я заметил, что в C я использовал структуры так же, как и классы, которые могли быть хорошими или плохими (я знаю C, но я не C-ace). Применяются аналогичные вещи?