Отключение, которое вы видите, не FP или OOP. В основном речь идет об неизменяемости и математических формализмах против изменчивости и неформальных подходов.
Во-первых, давайте избавимся от проблемы изменчивости: у вас может быть FP с изменяемостью и ООП с неизменяемостью. Еще более функциональный, чем ты, Haskell позволяет вам играть с изменяемыми данными все, что вы хотите, вам просто нужно четко указать, что является изменчивым и порядок, в котором все происходит; и кроме соображений эффективности, почти любой изменяемый объект может создавать и возвращать новый, «обновленный» экземпляр вместо изменения своего собственного внутреннего состояния.
Большей проблемой здесь являются математические формализмы, в частности интенсивное использование алгебраических типов данных на языке, мало удаленном от лямбда-исчисления. Вы пометили это с помощью Haskell и F #, но понимаете, что это только половина вселенной функционального программирования; Семейство Lisp имеет совершенно другой, гораздо более свободный характер по сравнению с языками в стиле ML. Большинство широко используемых сегодня ОО-систем носят очень неформальный характер - формализмы существуют для ОО, но они явно не вызываются так, как формализмы FP в языках стиля ML.
Многие из очевидных конфликтов просто исчезают, если вы удалите несоответствие формализма. Хотите построить гибкую, динамическую, специальную ОО-систему поверх Lisp? Давай, это будет работать просто отлично. Хотите добавить формализованную неизменяемую ОО-систему к языку в стиле ML? Нет проблем, просто не ожидайте, что он будет хорошо работать с .NET или Java.
Теперь вам может быть интересно, что является подходящим формализмом для ООП? Ну, вот изюминка: во многих отношениях она более функционально ориентирована, чем FP в стиле ML! Я вернусь к одной из моих любимых статей для того, что кажется ключевым отличием: структурированные данные, такие как алгебраические типы данных в языках стиля ML, предоставляют конкретное представление данных и возможность определять операции в теме; объекты обеспечивают абстракцию черного ящика над поведением и возможность легко заменять компоненты.
Здесь есть двойственность, которая гораздо глубже, чем просто FP против ООП: она тесно связана с тем, что некоторые теоретики языка программирования называют Проблема выражения : С конкретными данными вы можете легко добавлять новые операции, которые работают с это, но изменить структуру данных сложнее. С объектами вы можете легко добавлять новые данные (например, новые подклассы), но добавление новых операций затруднительно (подумайте о добавлении нового абстрактного метода в базовый класс со многими потомками).
Причина, по которой я говорю, что ООП является более функционально-ориентированной, заключается в том, что сами функции представляют собой форму поведенческой абстракции. Фактически, вы можете смоделировать структуру в стиле OO в чем-то наподобие Haskell, используя записи, содержащие набор функций в качестве объектов, позволяя типу записи быть своего рода «интерфейс» или «абстрактный базовый класс» и заменяя функции, создающие записи. конструкторы классов. Таким образом, в этом смысле ОО-языки используют функции высшего порядка гораздо чаще, чем, скажем, Хаскелл.
В качестве примера такого дизайна, который на самом деле очень хорошо используется в Haskell, прочитайте исходный код пакета graphics-drawingcombinators , в частности, о том, как он использует непрозрачный тип записи, содержащий функционирует и объединяет вещи только с точки зрения их поведения.
РЕДАКТИРОВАТЬ: Несколько последних вещей, которые я забыл упомянуть выше.
Если ОО действительно широко использует функции более высокого порядка, на первый взгляд может показаться, что он вполне естественно вписывается в функциональный язык, такой как Haskell. К сожалению, это не совсем так. Это правда, что объекты , как я их описал (см. Статью, упомянутую в ссылке на LtU), подходят просто отлично. на самом деле результатом является более чистый стиль ОО, чем у большинства языков ОО, поскольку «закрытые члены» представлены значениями, скрытыми замыканием, используемым для создания «объекта», и недоступны ни для чего, кроме одного конкретного экземпляра. Вы не становитесь намного более приватным, чем это!
Что не очень хорошо работает в Haskell, так это подтип . И хотя я думаю, что наследование и подтипы слишком часто неправильно используются в ОО-языках, некоторая форма подтипирования весьма полезна для возможности комбинировать объекты гибкими способами. Хаскеллу не хватает врожденного понятия о подтипах, и замены, сделанные вручную, обычно бывают очень неуклюжими.
Кроме того, большинство ОО-языков со статическими системами типов также создают полный хэш подтипов, поскольку они слишком слабы с подстановкой и не обеспечивают надлежащей поддержки дисперсии в сигнатурах методов. На самом деле, я думаю, что единственный полноценный ОО-язык, который не испортил его полностью, по крайней мере, я знаю, это Scala (F #, казалось, слишком много уступал .NET, хотя, по крайней мере, я не думаю, что он делает любые новые ошибки). У меня ограниченный опыт работы со многими такими языками, поэтому я определенно могу ошибаться.
На заметке, относящейся к Haskell, его "классы типов" часто выглядят заманчиво для программистов ОО, на что я говорю: не ходите туда. Попытка реализовать ООП таким способом закончится слезами. Думайте о классах типов как о замене перегруженных функций / операторов, а не ООП.