История языка Haskell начинается в 1987 году. В 1980е годы наблюдался всплеск интереса к ленивой стратегии вычислений. Один за другим появлялись новые функциональные языки программирования. Программисты задумались и решили, объединив усилия, найти общий язык. Так появился Haskell. Он был назван в честь одного из основателей комбинаторной логики Хаскеля Кэрри (Haskell Curry).
Новый язык должен был стать свободным языком, пригодным для исследовательской деятельности и решения практических задач. Свободные языки основаны на стандарте, который формулируется комитетом разработчиков. Дальше любой желающий может заняться реализацией стандарта, написать компилятор языка. Первая версия стандарта была опубликована 1 апреля 1990 года. Haskell продолжает развиваться и сегодня, было зафиксировано два стандарта: 1998 и 2010 года. Это стабильные версии. Но кроме них в Haskell включается множество расширений, проходит обкат интересных идей. Сегодня Haskell переживает бурный рост, к сожалению, эпицентры далеки от России, это Англия, Нидерланды, Америка и Австралия. Интерес к Haskell вызван популярностью многопроцессорных технологий. Модель вычислений Haskell хорошо подходит для распараллеливания. И сейчас проводятся исследования в этой области.
Haskell очень красивый и лаконичный язык. Он придётся по душе математикам, программистам, склонным к поиску элегантных решений. В арсенале программиста: строгая типизация с выводом типов, функции высшего порядка, алгебраические типы данных, алгебраические структуры. Если пока всё это звучит как набор слов, ничего страшного, вы узнаете что это по ходу чтения книги.
Haskell славится высоким порогом вхождения. Он считается трудным языком для начинающих. Во многом это связано с тем, что начинающие уже имеют приличный опыт программирования на императивных языках. И при первом знакомстве оказывается, что этот опыт ничем не может им помочь. Они не могут найти в Haskell аналогов привычных синтаксических конструкций и приёмов программирования. Haskell сильно отличается от распространённых языков программирования. Но если вы совсем-совсем начинающий, скорее всего в этом плане вам будет гораздо проще. Если вы всё же не начинающий, попробуйте подойти к материалу этой книги с открытым сердцем. Не ищите в Haskell элементы вашего любимого языка и, возможно, таким языком станет Haskell.
Ещё одна трудность связана с тем, что многие понятия тесно переплетены, Haskell не так просто разбить на маленькие части и изучать их от простого к сложному, уже в самых простейших элементах кроются черты новых и непривычных идей. Но, я надеюсь, что мы сможем преодолеть и этот барьер, мы не будем изучать Haskell по кусочкам, а окунёмся в него с головой, уже в первой главе мы пробежимся по всему языку и далее будем углубляться в отдельные моменты.
В книге много примеров. Haskell оснащён интерпретатором. Интерпретатор (также называемый REPL, от англ. read-eval-print loop) позволяет писать программы в диалоговом режиме. Мы набираем выражение языка и сразу видим ответ – вычисленное значение. Интерпретатор поможет нам разобраться во многих тонкостях языка. Мы будем обращаться к нему очень часто.
Книгу можно разбить на несколько частей:
Основы языка (1-13). Из первых тринадцати глав вы узнаете, что такое Haskell и чем он хорош.
Теоретическая часть (14-16). Haskell питается соками математики, многие красивые научные идеи не только находят в нём воплощение, но и являются фундаментом языка. Из этих глав вы узнаете немного теории, которая служила источником вдохновения разработчиков Haskell.
Разработка на Haskell (10,17-20). В этих главах мы познакомимся с расширениями языка (17), мы узнаем как писать библиотеки и документацию (18), проводить тестирование и оценивать быстродействие программ (19), также мы потренируемся в написании императивного кода на Haskell (20). Из главы 10 мы узнаем как работает GHC, основной компилятор для Haskell.
Примеры (13, 21). В этих главах мы посмотрим на несколько примеров применения Haskell. В главе 13 мы напишем программу для игры в пятнашки, а в главе 21 – midi-секвенсор и немного музыки.
Рекомендую сначала изучить основы языка, а затем обращаться к остальным частям в любом порядке.
Haskell – чисто функциональный, типизированный язык программирования. Я буду очень часто говорить слова функция, типы, значения, типы, функция, функция, типы~– буквально постоянно. Перед тем как мы окунёмся с головой в программный код, я бы хотел словами пояснить, что всё это значит.
Мы собираемся изучить новый язык, хоть и искусственный, но всё же язык. Языки служат описанию явлений, словами мы можем зафиксировать мысли и чувства и передать их другому. Предложение языка описывает что-то. У нас будут два разных вида описаний. Одни говорят о чём-то конкретном, их мы будем называть значениями, а другие говорят о самих описаниях. Например это слова “числа”, “цвета” или “люди”. Есть конкретное число: один два или три, а есть все числа. Такие описания мы будем называть типами. Типы описывают множество значений. Функции описывают одни значения через другие. Это такие шаблоны описаний. Типичный пример функции, это “вычисление площади треугольника”. Функция как бы говорит: если ты мне покажешь треугольник, то я тебе скажу его площадь (число). Функция “вычисление площади треугольника” связывает два типа между собой: тип всех треугольников и тип чисел (значение площади). Могут быть и не математические функции. Например функция “цвет глаз” говорит нам: если ты покажешь мне человека, то я скажу какого цвета у него глаза. Эта функция связывает тип “люди” и тип “цвет”. При этом связь имеет направление. Функция сначала спрашивает у нас, чего ей не хватает, а потом говорит ответ. Ответ называют значением функции (или выходом функции), а то чего ей не хватает аргументами функции (или входами). Математики говорят, что эта функция отображает значения типа “люди” в значения типа “цвет”. В Haskell функции тоже являются значениями. Функция может принимать в качестве аргумента функцию и возвращать функцию.
Функции бывают чистыми и с побочными эффектами. Чистые функции – это правдивые функции. Их основная особенность в том, что для одинаковых ответов на их вопросы, они скажут одинаковые ответы. Функции с побочными эффектами так не делают, например если мы спросим у такой функции какого цвета глаза у Коли? В один день она может сказать голубые, а в другой зелёные. В Haskell таким функциям не доверяют и огораживают их от чистых функций, но я увлёкся, обо всём об этом вы узнаете из этой книги.
Я бы хотел поблагодарить родителей за терпение и поддержку, сообщество Haskell, всех тех людей, у которых я мог свободно учится языку Haskell. Когда я только начинал мне очень помогли книга Мирана Липовача (Miran Lipovaca) Learn You A Haskell for a Great Good и книга Хал Дама (Hal Daume III) Yet another Haskell Tutorial. Спасибо Дмитрию Астапову, Дугласу Мак Илрою (Douglas McIlroy) и Джону Хьюзу (John Huges) за великодушное согласие на использование примеров из их статей. Большое спасибо Кате Столяровой за идею написания книги. Спасибо Александру Мозгунову за расширение моего кругозора в Haskell и не только. Спасибо Оксане Станевич за поддержку, а также за редактирование первой главы.
Хочется поблагодарить тех, кто присылал правки, после появления первой версии книги. Огромное спасибо Андрею Мельникову. Его поддержка и замечания значительно углубили материал книги, вывели её на новый уровень. Книга сильно изменилась после комментариев Владимира Шабанова (появились части о сборщике мусора). Многие правки внесли Евгений Бахвалов, Сергей Дмитриев, Кирилл Заборский и Михаил Печкин. Также хотелось бы отметить тех, кто вносил правки через github и ru_declarative: lionet, d_ao, odrdo, ul.
Технические благодарности: команде GHC, за компилятор Haskell, Джону Мак Фарлану (John MacFarlane) за систему вёрстки pandoc, команде TexLive, авторам XeLatex, автору пакета hscolour Малькольму Уолласу (Malcolm Wallace) за подсветку синтаксиса, авторам пакетов c Hackage: diagrams (Брент Йорги (Brent Yorgey), Райан Йэйтс (Ryan Yates)) QuickCheck (Коэн Клаессен (Koen Claessen), Бьорн Брингерт (Bjorn Bringert), Ник Смолбоун (Nick Smallbone)), criterion (Брайан О’Салливан (Bryan O’Sullivan)), HCodecs (Джордж Гиоргадзе (George Giorgidze)), fingertree (Росс Патерсон (Ross Paterson), Ральф Хинце (Ralf Hinze)), Hipmunk (Фелипе Лесса (Felipe A. Lessa)), OpenGL (Джэйсон Даджит (Jason Dagit), Свен Пэнн (Sven Panne) и GLFW (Пол Лю (Paul H. Liu), Марк Санет (Marc Sunet)).