Ответ 1
Фантастический вопрос!
Вот ответ, полученный из этой статьи в блоге:
Функциональная парадигма (то есть использование функций более высокого порядка) обеспечивает только одну форму расширяемости: функции более высокого порядка. Это позволяет вам учитывать "внутренние" функции. Например, код, который часто появляется с тем же первым и последним кодовыми блоками:
let f x =
first x
stuff1 x
last x
let g x =
first x
stuff2 x
last x
может быть учтено в общую функцию высшего порядка, которая повторно используется из конкретных случаев:
let hof stuff x =
first x
stuff x
last x
let f = hof stuff1 x
let g = hof stuff2 x
Применение этого агрессивно приводит к таким шаблонам проектирования, как комбинаторы парсеров, и является очень мощным и легким методом для расширения кода. Однако он не делает типы данных расширяемыми.
Но реальные языки функционального программирования почти всегда включают в себя более сложные функции языка, которые помогают с расширяемостью:
- Common Lisp имеет общую Lisp систему объектов (CLOS) и макросистему.
- Стандарт ML имеет параметрический полиморфизм и систему модулей более высокого порядка.
- OCaml добавил полиморфные варианты, объекты, необязательные аргументы и макросистему Camlp4.
- Haskell имеет параметрический полиморфизм и классы типов, а Template Haskell добавляет макросы.
- Scala имеет ООП в стиле Java с некоторыми дополнительными функциями.
Прочитайте замечательную монографию Криса Окасаки. Чисто функциональные структуры данных для некоторых замечательных примеров с использованием модулей более высокого порядка в стандартных классах ML и типов в Haskell. Прочитайте повторное использование кода через полиморфные варианты Жака Гаррига для описания того, как эта функция языка может использоваться для атаки на проблему выражения. Однако эти решения довольно редки в дикой природе, и, в частности, вы можете пройти долгий путь без них (например, в F #).
Исторически сложилось так, что это разнообразие появилось потому, что большинство функциональных языков программирования были исследовательскими проектами, и, следовательно, они существовали для добавления новых функций. Поэтому теперь у нас есть множество разнородных форм расширяемости в современных функциональных языках программирования.
F # - другой зверь, потому что его требования к дизайну были бесшовной совместимостью с остальной частью .NET(которая накладывает OOP в стиле .NET) и прагматизмом. Следовательно, F # сохраняет ядро ML с параметрическим полиморфизмом и добавляет объектную систему .NET. Таким образом, вы можете извлечь выгоду из простой расширяемости, предлагаемой универсальными функциями более высокого порядка и обычным ООП, но не из любых более эзотерических функций, таких как модули более высокого порядка, классы классов и макросы.
Единственная форма расширяемости F #, которая была впервые использована, - активные шаблоны. Они позволяют разделить код, который разрушает с помощью сопоставления шаблонов из конкретного представления данных. Это важный способ отделить код от данных и, следовательно, сделать его более многоразовым.