Введение. Функциональное программирование.
Функциональное программирование – раздел дискретной математики и парадигма программирования, в которой процесс вычисления трактуется как вычисление значений функций в математическом понимании последних (в отличие от функций как подпрограмм в процедурном программировании).
Противопоставляется парадигме императивного программирования, которая описывает процесс вычислений как последовательное изменение состояний (в значении, подобном таковому в теории автоматов). При необходимости, в функциональном программировании вся совокупность последовательных состояний вычислительного процесса представляется явным образом, например, как список.
Формальной основой функционального программирования является лямбда-исчисление (λ-исчисление), математический формализм, описывающий абстрактное вычисление на основе “функций”. Близок к формализму частично-рекурсивных функций.
В противовес, формальной основой императивного программирования можно считать машины Тьюринга или Поста.
Ключевым отличием математической функции от “функции” в императивных языках является отсутствие так называемых “побочных эффектов”. Математическая функция при вычислении не изменяет и не хранит никакого скрытого глобального или локального состояния, не работает с устройствами, не запускает ядерные ракеты. Одним из следствий этого свойства является то, что результат вычисления такой функции зависит только от значений аргументов.
Понятно, что, абсолютно “чистый” функциональный подход достаточно бесполезен в отсутствие возможностей ввода-вывода. Разные функциональные языки решают эту проблему по-разному. Забегая вперёд, Haskell решает её, по-видимому, настолько формально корректно, насколько возможно.
Применение функционального подхода, хотя в общем случае может быть менее эффективно в смысле использования ресурсов вычислительного устройства (но следует отметить, что иногда функциональные алгоритмы оказываются более эффективными), во многих случаях приводит к более простому, ёмкому, читаемому и поддерживаемому коду, чем применение императивного. Отдельно следует отметить, что функциональный подход гораздо легче использовать для параллельных вычислений (как следствие отсутствия неявного состояния).
Язык Haskell
Haskell – открытый, стандартизированный, компилируемый, чистый функциональный язык программирования общего назначения, со статической строгой типизацией, выведением типов и ленивыми (отложенными, нестрогими) вычислениями.
Язык назван в честь исследователя теории типов и изобретателя комбинаторной логики Хаскелла Карри.
Имеются средства взаимодействия с кодом на других языках программирования. Есть встроенная поддержка многозадачного и параллельного программирования, развитый инструментарий (средства автоматического тестирования, отладки и профилирования, в том числе для параллельных программ), существует несколько тысяч библиотек с открытым исходным кодом.
Предшественником Haskell был язык Miranda, разработанный в 1985 Дэвидом Тёнрером, на основе, в числе прочего, концепций из языка ML, который, в свою очередь, является своего рода компромиссом между системой типов ALGOL и функциональной чистотой Lisp. К 1987 году, существовало около полутора десятков различных чистых функциональных языков с ленивыми вычислениями, большинство из которых были проприетарными. В 1987 году был образован комитет, целью которого было разработать открытый стандарт ленивого чисто функционального языка, который бы вобрал в себя достоинства и учёл недостатки существующих на тот момент.
Первая версия стандарта Haskell выпущена в 1990 году. К 1998 году, выпущена стабильная версия стандарта, названная Haskell 98. Эта версия получила исправления и дополнения в 2003 году. Новая версия стандарта, Haskell 2010, выпущена в 2010 году. Дальнейшие работы по разработке языка ведутся в рамках инициативы Haskell’ (Haskell Prime).
Основным на текущий момент компилятором для языка Haskell является компилятор университета Глазгоу – GHC (Glasgow Haskell Compiler), на данный момент разрабатываемый в рамках программы Microsoft Research. GHC является свободным программным обеспечением и распространяется на условиях “новой” лицензии BSD. В основном на базе GHC разрабатываются и испытываются расширенные возможности языка, не включённые ещё в стандарт.
Иногда можно услышать мнение, что Haskell является “академическим” языком, поскольку часто новые “открытия” в области дизайна языков программирования реализуются в GHC раньше, чем большинство программистов на других языках узнают об этих “открытиях”. На мой вкус, это не делает Haskell “академическим”, это делает его “активно развивающимся”, хотя некоторые из таких возможностей языка может быть сложно понять без соответствующей теоретической подготовки. У активно развивающихся языков, конечно, есть свои минусы – в частности, необходимость регулярно обновлять кодовую базу для совместимости с новыми версиями компилятора. Однако, языки, которые не развиваются, стремительно теряют актуальность.
Многие наработки, впервые реализуемые в рамках Haskell, впоследствии оказывают влияние на более “общепринятые” языки, в том числе императивные и объектно-ориентированные, в частности C++, C#, Java, Python, Rust и др.
Экосистема Haskell
Помимо, собственно, компилятора, для Haskell существуют и другие компоненты экосистемы.
Существуют две системы сборки проектов, cabal-install и stack. Обе основаны на библиотеке обработки описаний проектов и зависимостей между ними Cabal. Обе используют он-лайн каталог пакетов Hackage.
Hackage представляет из себя он-лайн каталог открытых исходных текстов пакетов ПО на языке Haskell, в основном библиотек самого разного назначения, от веб-серверов до компиляторов.
Кроме компилятора GHC, существует интерпретатор и отладчик GHCi.
Вопрос с IDE – несколько болезненный. Варианты есть, но разработка пока ведётся, и не сказать чтобы очень быстрыми темпами.