Введение

Об этом учебнике

Добро пожаловать на Выучи Haskell ради Добра! Если вы читаете это, скорее всего вы хотите выучить Haskell. Ну, вы оказались в правильном месте, но давайте сперва немного поговорим об этом учебника.

Я решился написать это руководство потому, что захотел упорядочить свои собственные знания о Haskell, и потому, что я, думаю, смогу помочь людям в изучении языка, как я его понимаю. В сети Интернет доступно уже достаточно много руководств по изучению языка Haskell, и когда я впервые начинал им заниматься, то изучал разные ресурсы. Избранный мною путь изучения — это чтение различных руководств и статей, потому что каждое из них описывало что-нибудь своим способом, отличным от остальных. Пройдясь по нескольким, я смог собрать воедино все эти «кусочки» и теперь они попали сюда. Так что эта статья — еще одна попытка добавить полезный ресурс для изучения Haskell, и есть вероятность, что вы найдете здесь то, что понравится лично вам.

bird

Данное руководство нацелено на людей, которые уже имеют опыт в императивных языках программирования (C, C++, Java, Python...), но ранее не программировавших на функциональных языках (Haskell, ML, OCaml...). Хотя, бьюсь об заклад, что даже если вы не обладаете значимым опытом программирования, то такие умные малые, как вы, будут в состоянии следовать руководству и смогут изучить Haskell.

Канал #haskell на Freenode Network — это прекрасное место для вопросов, если вы почувствуете, что «застряли». Люди там чрезвычайно приятные, вежливые и сочувствуют новичкам.

Мои попытки изучать Haskell были неудачны, примерно пару раз, прежде чем я наконец-то ухватил суть, потому что все выглядело странно и я просто ничего не понял. И когда все прояснилось, после сложностей вначале, все пошло как по маслу. Думаю, я хочу сказать: Haskell — великий язык, и если вас интересует программирование, то вы действительно должны изучить его, и даже если в начале все выглядит запутанно. Изучение Haskell более похоже на первое изучение программирования — это очень занимательно! Оно заставляет мыслить иначе, что подводит нас к следующему разделу…

Так что же такое Haskell?

fx Haskell — это чистый функциональный язык программирования. В императивных языках результат получается от передачи компьютеру последовательности команд, который он затем выполняет. Выполняя ваши команды, компьютер может изменять свое состояние. Например, мы устанавливаем переменную A равной 5 и что-нибудь делаем, и затем устанавливаем ее равной чему-нибудь еще. Еще у вас есть операторы управления выполнением, чтобы повторять какие-то действия несколько раз. В чисто функциональных языках вы не говорите компьтеру как именно делать, скорее вы говорите, что представляет собой ваша проблема. Факториал числа — это произведение целых чисел от 1 до этого числа, сумма списка чисел — это первое число плюс сумма всех остальных чисел, и так далее. Вы выражаете это в виде функций и не можете присвоить переменной A значение, а затем присвоить что-нибудь еще. Если вы сказали, что A равна 5, то нельзя позднее нельзя сказать, что она равна другому значению, потому что вы уже сказали, что она равна 5. В конце концов вы что, врун какой-нибудь? В итоге, в чистых функциональных языках у функций отсутствуют побочные эффекты. Только одну вещь может cделать функция — это рассчитать что-нибудь и возвратить это как результат. Поначалу это выглядит как ограничение, но в действительности имеет положительные последствия: если функция вызывается дважды с одними и теми же параметрами — это гарантирует, что вернется одинаковый результат. Такие функции называются «чистыми» и не только позволяют компилятору получить информацию о поведении программы, но и дают возможность вам легко вывести (и даже доказать), что функция корректна, а также строить более сложные функции, объединяя их вместе с простыми.

lazy Haskell — ленивый язык. Это означает, что язык не будет выполнять функции и проводить вычисления пока это действительно вам не потребовалось для вывода результата, если иное поведение не указано явно. Это хорошо согласуется с чистыми функциями и позволяет вам думать о программе как о наборе преобразований данных. Что, например, допускает такие отличные вещи, как бесконечные структуры данных. Допустим, у вас есть неизменяемый список чисел xs = [1,2,3,4,5,6,7,8] и функция doubleMe(«УдвойМеня»), которая умножает каждый элемент на 2 и затем возвращает новый список. Если мы захотим умножить наш список на 8 в императивных языках, то сделаем так: doubleMe(doubleMe(doubleMe(xs))), что при вызове, вероятно, получит список, создаст копию и вернет ее. Затем получит список еще два раза и вернет результат. В ленивых языках программирования, вызов doubleMe со списком, без форсирования получения результата, в программе скажет вам что-то типа: «Да-да, я сделаю это позже!». Но когда вы захотите увидеть результат, то первая функция doubleMe tскажет второй, что ей требуется результат, и немедленно! Вторая функция скажет третьей, и та неохотно вернет удвоенную 1, т.е. 2. Вторая получит и вернет первой функции результат — 4. Первая увидит результат и выдаст вам 8. Так что потребуется только один проход по списку, и он будет выполнен только тогда, когда действительно необходим. Таким образом, когда ты хочешь что-то от ленивого языка, ты можешь просто взять входные данные и эффективно преобразовать и «подшить» их так, чтобы в конце они были похожи на то, что тебе надо.

boat Haskell — статически типизированный язык. Когда вы компилируете вашу программу, то компилятор знает, какой кусок кода — число, какой — строка и т.д. Это означает, что множество возможных ошибок будут обнаружены во время компиляции. Если вы захотите сложить вместе число и строку, то компилятор вам пожалуется. Haskell имеет очень хорошую систему типов, которая умеет делать вывод типов.На практике это означает, что вам не нужно описывать типом в каждом куске кода, потому что система типов может вычислить это сама. Если, скажем, a = 5 + 4 то вы не говорите, что a — число, так как это может быть выведено автоматически. Вывод типов делает ваш код более универсальным. Если функция принимает два параметра и складывает их вместе, и при этом тип параметров явно не задан, то функция будет работать с любыми двумя параметрами, которые ведут себя как числа.

Haskell — ясный и выразительный язык. потому что он использует множество высокоуровневых идей; программы обычно короче, чем их императивные эквиваленты, их легче сопровождать, в них меньше ошибок.

Haskell был придуман несколькими действительно умными ребятами (кандидатами наук с PhD). Работа над языком Haskell началась в 1987 году, когда комитет исследователей собрался для разработки нового языка, который всех порвет. В 2003 году был впервые опубликован Haskell Report, что ознаменовало возникновение стабильной версии языка.

Что нужно для погружения

На сегодня существуют два основных компилятора языка Haskell — это GHC (Glasgow Haskell Compiler) и Hugs. Я не буду заостряться на деталях их установки. Текстовый редактор и компилятор языка Haskell. Вероятно, у вас уже установлен любымый редактор, так что не будем тратить на него время. Для достижений целей учебника, мы будем использовать GHC, наиболее используемый компилятор Haskell. Наилучший способ начать - загрузить Haskell Platform, в которую включены все батарейки.

GHC может принимать и компилировать файлы скриптов на языке Haskell (обычно у них расширение .hs), а так же имеет интерактивную среду, которая позволяет интерактивно взаимодействовать со скриптами. Все это интерактивно! Вы сможете вызывать функции из загруженных файлов и тут же получить результат. Во время обучения языку — этот подход намного проще и быстрее, чем компилировать и запускать раз за разом, когда меняется скрипт. Интерактивная среда вызывается запуском ghci в вашей оболочке. Если, скажем, у вас в файле myfunctions.hsопределены функции, то для их загрузки достаточно набрать :l myfunctions и легко с ними «поиграть», только если файл myfunctions.hs находится в том же каталоге, откуда был вызван ghci. При внесении изменений в скрипт достаточно снова выполнить :l myfunctions или просто :r, что то же самое, так как заново загружает текущий файл. Обычно, я делаю следующим образом, когда решаю потренироваться — объявляю функции в .hs файле, загружаю его, поиграюсь с функциями и вношу изменения в .hs файл, снова загружаю и так далее. Это именно то, чем мы тут и займемся.

Hosted by uCoz