Миран Липовача - Изучай Haskell во имя добра!
- Название:Изучай Haskell во имя добра!
- Автор:
- Жанр:
- Издательство:ДМК Пресс
- Год:2012
- Город:Москва
- ISBN:978-5-94074-749-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Миран Липовача - Изучай Haskell во имя добра! краткое содержание
Язык Haskell имеет множество впечатляющих возможностей, но главное его свойство в том, что меняется не только способ написания кода, но и сам способ размышления о проблемах и возможных решениях. Этим Haskell действительно отличается от большинства языков программирования. С его помощью мир можно представить и описать нестандартным образом. И поскольку Haskell предлагает совершенно новые способы размышления о проблемах, изучение этого языка может изменить и стиль программирования на всех прочих.
Ещё одно необычное свойство Haskell состоит в том, что в этом языке придаётся особое значение рассуждениям о типах данных. Как следствие, вы помещаете больше внимания и меньше кода в ваши программы.
Вне зависимости от того, в каком направлении вы намерены двигаться, путешествуя в мире программирования, небольшой заход в страну Haskell себя оправдает. А если вы решите там остаться, то наверняка найдёте чем заняться и чему поучиться!
Эта книга поможет многим читателям найти свой путь к Haskell.
Отображения, монады, моноиды и другое! Всё сказано в названии: «Изучай Хаскель во имя добра!» – весёлый иллюстрированный самоучитель по этому сложному функциональному языку.
С помощью оригинальных рисунков автора, отсылке к поп-культуре, и, самое главное, благодаря полезным примерам кода, эта книга обучает основам функционального программирования так, как вы никогда не смогли бы себе представить.
Вы начнете изучение с простого материала: основы синтаксиса, рекурсия, типы и классы типов. Затем, когда вы преуспеете в основах, начнется настоящий мастер-класс от профессионала: вы изучите, как использовать аппликативные функторы, монады, застежки, и другие легендарные конструкции Хаскеля, о которых вы читали только в сказках.
Продираясь сквозь образные (и порой безумные) примеры автора, вы научитесь:
• Смеяться в лицо побочным эффектам, поскольку вы овладеете техниками чистого функционального программирования.
• Использовать волшебство «ленивости» Хаскеля для игры с бесконечными наборами данных.
• Организовывать свои программы, создавая собственные типы, классы типов и модули.
• Использовать элегантную систему ввода-вывода Хаскеля, чтобы делиться гениальностью ваших программ с окружающим миром.
Нет лучшего способа изучить этот мощный язык, чем чтение «Изучай Хаскель во имя добра!», кроме, разве что, поедания мозга его создателей. Миран Липовача (Miran Lipovača) изучает информатику в Любляне (Словения). Помимо его любви к Хаскелю, ему нравится заниматься боксом, играть на бас-гитаре и, конечно же, рисовать. У него есть увлечение танцующими скелетами и числом 71, а когда он проходит через автоматические двери, он притворяется, что на самом деле открывает их силой своей мысли.
Изучай Haskell во имя добра! - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
gchi> putStrLn "При-и-и-вет"
При-и-и-вет
Даже если мы просто наберём некоторое число или вызовем некоторую функцию в GHCi и нажмём Enter, интерпретатор GHCi вычислит значение, затем вызовет для него функцию show
, чтобы получить строку, и напечатает строку на терминале, используя функцию putStrLn
.
Использование ключевого слова let внутри блока do
Помните связывания при помощи ключевого слова let
? Если уже подзабыли, освежите свои знания. Связывания должны быть такого вида: let < определения > in < выражение >
, где < определения >
– это имена, даваемые выражениям, а < выражение >
использует имена из < определений >
. Также мы говорили, что в списковых выражениях часть in
не нужна. Так вот, в блоках do
можно использовать выражение let
таким же образом, как и в списковых выражениях. Смотрите:
import Data.Char
main = do
putStrLn "Ваше имя?"
firstName <���– getLine
putStrLn "Ваша фамилия?"
lastName <���– getLine
let bigFirstName = map toUpper firstName
bigLastName = map toUpper lastName
putStrLn $ "Привет, " ++ bigFirstName ++ " "
++ bigLastName
++ ", как дела?"
Видите, как выровнены операторы действий ввода-вывода в блоке do
? Обратите внимание и на то, как выровнено выражение let
по отношению к действиям ввода-вывода и как выровнены образцы внутри выражения let
. Это хороший пример, потому что выравнивание текста очень важно в языке Haskell. Далее мы записали вызов map
toUpper
firstName
, что превратит, например, "Иван"
в намного более солидное "ИВАН"
. Мы связали эту строку в верхнем регистре с именем, которое использовали в дальнейшем при выводе на терминал.
Вам может быть непонятно, когда использовать символ <���–
, а когда выражение let
. Запомните: символ <���–
(в случае действий ввода-вывода) используется для выполнения действий ввода-вывода и связывания результатов с именами. Выражение map toUpper firstName
не является действием ввода-вывода – это чистое выражение. Соответственно, используйте символ <���–
для связывания результатов действий ввода-вывода с именами, а выражение let
– для связывания имён с чистыми значениями. Если бы мы выполнили что-то вроде let firstName = getLine
, то просто создали бы синоним функции getLine
, для которого значение всё равно должно получаться с помощью символа <���–
.
Обращение строк
Теперь напишем программу, которая будет считывать строки, переставлять в обратном порядке буквы в словах и распечатывать их. Выполнение программы прекращается при вводе пустой строки. Итак:
main = do
line <���– getLine
if null line
then return ()
else do
putStrLn $ reverseWords line
main
reverseWords :: String –> String
reverseWords = unwords . map reverse . words
Чтобы лучше понять, как работает программа, сохраните её в файле reverse.hs , скомпилируйте и запустите:
$ ghc reverse.hs
[1 of 1] Compiling Main ( reverse.hs, reverse.o )
Linking reverse ...
$ ./reverse
уберитесь в проходе номер 9
ьсетиребу в едохорп ремон 9
козёл ошибки осветит твою жизнь
лёзок икбишо титевсо юовт ьнзиж
но это всё мечты
он отэ ёсв ытчем
Для начала посмотрим на функцию reverseWords
. Это обычная функция, которая принимает строку, например "эй ты мужик"
, и вызывает функцию words
, чтобы получить список слов ["эй", "ты","мужик"]
. Затем мы применяем функцию reverse
к каждому элементу списка, получаем ["йэ","ыт","кижум"]
и помещаем результат обратно в строку, используя функцию unwords
. Конечным результатом будет "йэ ыт кижум"
.
Теперь посмотрим на функцию main
. Сначала мы получаем строку с терминала с помощью функции getLine
. Далее у нас имеется условное выражение. Запомните, что в языке Haskell каждое ключевое слово if
должно сопровождаться секцией else
, так как каждое выражение должно иметь некоторое значение. Наш оператор записан так, что если условие истинно (в нашем случае – когда введут пустую строку), мы выполним одно действие ввода-вывода; если оно ложно – выполним действие ввода-вывода из секции else
. По той же причине в блоке do
условные операторы if
должны иметь вид if < условие > then < действие ввода-вывода > else < действие ввода-вывода >
.
Вначале посмотрим, что делается в секции else
. Поскольку можно поместить только одно действие ввода-вывода после ключевого слова else
, мы используем блок do
для того, чтобы «склеить» несколько операторов в один. Эту часть можно было бы написать так:
else (do
putStrLn $ reverseWords line
main)
Подобная запись явно показывает, что блок do
может рассматриваться как одно действие ввода-вывода, но и выглядит она не очень красиво. В любом случае внутри блока do
мы можем вызвать функцию reverseWords
со строкой – результатом действия getLine
и распечатать результат. После этого мы выполняем функцию main
. Получается, что функция main
вызывается рекурсивно, и в этом нет ничего необычного, так как сама по себе функция main
– тоже действие ввода-вывода. Таким образом, мы возвращаемся к началу программы в следующей рекурсивной итерации.
Ну а что случится, если мы получим на вход пустую строку? В этом случае выполнится часть после ключевого слова then
. То есть выполнится выражение return ()
. Если вам приходилось писать на императивных языках вроде C, Java или на Python, вы наверняка уверены, что знаете, как работает функция return
– и, возможно, у вас возникнет искушение пропустить эту часть текста. Но не стоит спешить: функция return
в языке Haskell работает совершенно не так, как в большинстве других языков! Её название сбивает с толку, но на самом деле она довольно сильно отличается от своих «тёзок». В императивных языках ключевое слово return
обычно прекращает выполнение метода или процедуры и возвращает некоторое значение вызывающему коду. В языке Haskell (и особенно в действиях ввода-вывода) одноимённая функция создаёт действие ввода-вывода из чистого значения. Если продолжать аналогию с коробками, она берёт значение и помещает его в «коробочку». Получившееся в результате действие ввода-вывода на самом деле не выполняет никаких действий – оно просто инкапсулирует некоторое значение. Таким образом, в контексте системы ввода-вывода return "ха-ха"
будет иметь тип IO String
. Какой смысл преобразовывать чистое значение в действие ввода-вывода, которое ничего не делает? Зачем «пачкать» нашу программу больше необходимого? Нам нужно некоторое действие ввода-вывода для второй части условного оператора, чтобы обработать случай пустой строки. Вот для чего мы создали фиктивное действие ввода-вывода, которое ничего не делает, записав return ()
.
Интервал:
Закладка: