О дивный новый мир ФП

Чтобы говорить о функциональном программировании, нужно сначала дать ему определение.

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

Другие возможные термины, связанные с ФП:
Неизменямость (immutability) — однажды присвоенное не переприсвоить.
Чистота (purity) — отсутствие побочных эффектов.
Рекурсивность (recursion) — способность функции вызывать саму себя (самый простой случай).
Ленивость (laziness) — вычисление совершается в тот момент, когда оно действительно нужно.
Ссылочная чистота (referential transparency) — вычисление можно заменить на результат вычисления.

Далее речь будет идти только о статически типизированном ФП.

Модульность — сила ФП

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

Вообще есть много докладов о том, что человеческий мозг работает следующим образом: чтобы решить некоторую проблему, он разбивает её на части, а затем каким-то образом эти части комбинирует. Соответственно степень, в которой мы можем программу модуляризировать, напрямую зависит от того, сможем ли мы сложить результат вместе. Функциональное программирование как раз предоставляет новый вид клея, который помогает собрать паззл разбитой на части проблемы, что позволяет решениям быть проще и понятнее.

Композиция функций

Первый вид клея нам хорошо известен и используется повсеместно — это композиция функций. ФП позволяет достаточно просто объединять входы и выходы функций и в результате получать функцию.

Допустим у нас есть функции a → b и b → c, соответственно объединив их, мы с легкостью получаем функцию a → c.

Моя статья о функциях и их применении:
https://bit.ly/2jv7jQo

Алгебраические типы данных

Второй вид нового типа клея, который мы рассмотрим — это алгебраические типы данных (АДТ). О них я также уже писал: 
https://bit.ly/2KD1lcD

Если вкратце, то это составные типы данных, представленные в терминах «И»и «ИЛИ». Часть, которая отвечает за «И» — это типы произведения (product types), а «ИЛИ» — типы суммы (sum types).
Соответственно человека можно представить в виде типа суммы:
человек бывает мужчиной ИЛИ женщиной. Ключевой момент в том, что человек не может одновременно быть мужчиной и женщиной (хотя учитывая последние достижения медицины кто-то мог бы и поспорить). «Человек» может состоять из имени И возраста И пола.

Как видно АДТ прекрасно подходят для описания состояния и при хорошо составленной иерархии можно не сомневаться в его непротиворечивости. Самый сок в том, что всё может быть проверено компилятором, и программист в данном случае уже точно не ошибётся. Чтобы полноценно утилизировать АДТ нужно сопоставление по образцу (pattern matching). Этот механизм позволяет разобрать структуру на части и написать для каждой свою логику обработки. Переиспользуя пример выше с сопоставлением по образцу, можно отправить женщин и мужчин в женскую и мужскую раздевалки.

Теория категорий

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

В сущности теория категорий — это алгебра функций, которая предоставляет некий мыслительный каркас, набор абстракций и правил для них. Самые известные абстракции, пожалуй, функтор и монада. О функторах я также писал: https://bit.ly/2jxrNrW.

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

Мифы о ФП

С функциональным программированием связано множество дискуссий и «мифов».

Медлительность

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

Сложность

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

В определенном смысле ООП со всеми иерархиям классов соответствует нашим простейшим представлениям о логике:
вот набор вещей, мы можем их классифицировать так и этак.
С другой стороны, ООП не всегда самый интуитивный способ восприятия мира. Если вспомнить книгу «Банды четырех», то можно найти множество шаблонов, которые логически являются скорее процессами, нежели объектами. Например шаблоны «стратегия» и «команда». В таких случаях ФП подходит лучше.

Сложность входа

Третий миф вытекает из второго — тяжело найти разработчиков. И это, к сожалению, правда. С другой стороны, можно увидеть и некоторую радужную сторону — если человек занимается ФП, значит он любознателен и будет тянуться к новому, хотя для компаний это далеко не всегда плюс. Есть еще одна оборотная сторона этой проблемы — часто функциональные решения излишне переусложнены, а порог вхождения слишком высок. Мне до сих пор не всегда понятны все исходные коды библиотек, а некоторая магия на типах ставит меня в ступор. Но это пространство для роста, конечно.

Вообще функциональное программирование набирает всё большую популярность. Думаю, это связано прежде всего с увеличивающейся производительностью компьютеров, а также со сложностью современных приложений, размеры которых давно перевалили за сотни тысяч строк и которым явно мало последовательного выполнения. Кстати говоря, параллельное выполнение — это область где ФП действительно сияет. Код, который утилизирует множество процессоров в функциональной парадигме, гораздо легче читать за счет неизменяемости и классных абстракций, которые позволяют не задумываться о синхронизациях и связанных с этим проблемах.

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

P.S. Если понравилась статья — то можно похлопать более 1 раза ;)