Миран Липовача - Изучай Haskell во имя добра!
- Название:Изучай Haskell во имя добра!
- Автор:
- Жанр:
- Издательство:ДМК Пресс
- Год:2012
- Город:Москва
- ISBN:978-5-94074-749-9
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Миран Липовача - Изучай Haskell во имя добра! краткое содержание
Язык Haskell имеет множество впечатляющих возможностей, но главное его свойство в том, что меняется не только способ написания кода, но и сам способ размышления о проблемах и возможных решениях. Этим Haskell действительно отличается от большинства языков программирования. С его помощью мир можно представить и описать нестандартным образом. И поскольку Haskell предлагает совершенно новые способы размышления о проблемах, изучение этого языка может изменить и стиль программирования на всех прочих.
Ещё одно необычное свойство Haskell состоит в том, что в этом языке придаётся особое значение рассуждениям о типах данных. Как следствие, вы помещаете больше внимания и меньше кода в ваши программы.
Вне зависимости от того, в каком направлении вы намерены двигаться, путешествуя в мире программирования, небольшой заход в страну Haskell себя оправдает. А если вы решите там остаться, то наверняка найдёте чем заняться и чему поучиться!
Эта книга поможет многим читателям найти свой путь к Haskell.
Отображения, монады, моноиды и другое! Всё сказано в названии: «Изучай Хаскель во имя добра!» – весёлый иллюстрированный самоучитель по этому сложному функциональному языку.
С помощью оригинальных рисунков автора, отсылке к поп-культуре, и, самое главное, благодаря полезным примерам кода, эта книга обучает основам функционального программирования так, как вы никогда не смогли бы себе представить.
Вы начнете изучение с простого материала: основы синтаксиса, рекурсия, типы и классы типов. Затем, когда вы преуспеете в основах, начнется настоящий мастер-класс от профессионала: вы изучите, как использовать аппликативные функторы, монады, застежки, и другие легендарные конструкции Хаскеля, о которых вы читали только в сказках.
Продираясь сквозь образные (и порой безумные) примеры автора, вы научитесь:
• Смеяться в лицо побочным эффектам, поскольку вы овладеете техниками чистого функционального программирования.
• Использовать волшебство «ленивости» Хаскеля для игры с бесконечными наборами данных.
• Организовывать свои программы, создавая собственные типы, классы типов и модули.
• Использовать элегантную систему ввода-вывода Хаскеля, чтобы делиться гениальностью ваших программ с окружающим миром.
Нет лучшего способа изучить этот мощный язык, чем чтение «Изучай Хаскель во имя добра!», кроме, разве что, поедания мозга его создателей. Миран Липовача (Miran Lipovača) изучает информатику в Любляне (Словения). Помимо его любви к Хаскелю, ему нравится заниматься боксом, играть на бас-гитаре и, конечно же, рисовать. У него есть увлечение танцующими скелетами и числом 71, а когда он проходит через автоматические двери, он притворяется, что на самом деле открывает их силой своей мысли.
Изучай Haskell во имя добра! - читать онлайн бесплатно ознакомительный отрывок
Интервал:
Закладка:
data Day = Monday | Tuesday | Wednesday | Thursday | Friday | Saturday | Sunday
deriving (Eq, Ord, Show, Read, Bounded, Enum)
Так как для нашего типа автоматически сгенерированы экземпляры классов Show
и Read
, можно конвертировать значения типа в строки и из строк:
ghci> Wednesday
Wednesday
ghci> show Wednesday
"Wednesday"
ghci> read "Saturday" :: Day
Saturday
Поскольку он имеет экземпляры классов Eq
и Ord
, допускаются сравнение и проверка на равенство:
ghci> Saturday == Sunday
False
ghci> Saturday == Saturday
True
ghci> Saturday > Friday
True
ghci> Monday `compare` Wednesday
LT
Наш тип также имеет экземпляр класса Bounded
, так что мы можем найти минимальный и максимальный день.
ghci> minBound :: Day
Monday
ghci> maxBound :: Day
Sunday
Благодаря тому что тип имеет экземпляр класса Enum
, можно получать предшествующие и следующие дни, а также задавать диапазоны дней.
ghci> succ Monday
Tuesday
ghci> pred Saturday
Friday
ghci> [Thursday .. Sunday]
[Thursday,Friday,Saturday,Sunday]
ghci> [minBound .. maxBound] :: [Day]
[Monday,Tuesday,Wednesday,Thursday,Friday,Saturday,Sunday]
Замечательно!
Синонимы типов

Ранее мы упоминали, что типы [Char]
и String
являются эквивалентами и могут взаимно заменяться. Это осуществляется с помощью синонимов типов. Синоним типа сам по себе ничего не делает – он просто даёт другое имя существующему типу, облегчая понимание нашего кода и документации. Вот так стандартная библиотека определяет тип String
как синоним для [Char]
:
type String = [Char]
Ключевое слово type
может ввести в заблуждение, потому что на самом деле мы не создаём ничего нового (создаём мы с помощью ключевого слова data
), а просто определяем синоним для уже существующего типа.
Если мы создадим функцию, которая преобразует строку в верхний регистр, и назовём её toUpperString
, то можем дать ей сигнатуру типа toUpperString :: [Char] –> [Char]
или toUpperString :: String –> String
. Обе сигнатуры обозначают одно и то же, но вторая легче читается.
Улучшенная телефонная книга
Когда мы работали с модулем Data.Map
, то вначале представляли записную книжку в виде ассоциативного списка, а потом преобразовывали его в отображение. Как мы уже знаем, ассоциативный список – это список пар «ключ–значение». Давайте взглянем на этот вариант записной книжки:
phoneBook :: [(String,String)]
phoneBook =
[("оля","555–29-38")
,("женя","452–29-28")
,("катя","493–29-28")
,("маша","205–29-28")
,("надя","939–82-82")
,("юля","853–24-92")
]
Мы видим, что функция phoneBook
имеет тип [(String,String)]
. Это говорит о том, что перед нами ассоциативный список, который отображает строки в строки, – но не более. Давайте зададим синоним типа, и мы сможем узнать немного больше по декларации типа:
type PhoneBook = [(String,String)]
Теперь декларация типа для нашей записной книжки может быть такой: phoneBook :: PhoneBook
. Зададим также синоним для String
.
type PhoneNumber = String
type Name = String
type PhoneBook = [(Name,PhoneNumber)]
Те, кто программирует на языке Haskell, дают синонимы типу String
, если хотят сделать объявления более «говорящими» – пояснить, чем являются строки и как они должны использоваться.
Итак, реализуя функцию, которая принимает имя и номер телефона и проверяет, есть ли такая комбинация в нашей записной книжке, мы можем дать ей красивую и понятную декларацию типа:
inPhoneBook :: Name –> PhoneNumber –> PhoneBook –> Bool
inPhoneBook name pnumber pbook = (name,pnumber) `elem` pbook
Если бы мы не использовали синонимы типов, тип нашей функции был бы String –> String –> [(String,String)] –> Bool
. В этом случае декларацию функции легче понять при помощи синонимов типов. Однако не надо перегибать палку. Мы применяем синонимы типов для того, чтобы описать, как используются существующие типы в наших функциях (таким образом декларации типов лучше документированы), или когда мы имеем дело с длинной декларацией типа, которую приходится часто повторять (вроде [(String,String)]
), причём эта декларация обозначает что-то более специфичное в контексте наших функций.
Параметризация синонимов
Синонимы типов также могут быть параметризованы. Если мы хотим задать синоним для ассоциативного списка и при этом нам нужно, чтобы он мог принимать любые типы для ключей и значений, мы можем сделать так:
type AssocList k v = [(k,v)]
Функция, которая получает значение по ключу в ассоциативном списке, может иметь тип (Eq
k)
=>
k
–>
AssocList
k
v
–>
Maybe
v
. Тип AssocList
– это конструктор типов, который принимает два типа и производит конкретный тип, например AssocList
Int
String
.
Мы можем частично применять функции, чтобы получить новые функции; аналогичным образом можно частично применять типы-параметры и получать новые конструкторы типов. Так же, как мы вызываем функцию, не передавая всех параметров для того, чтобы получить новую функцию, мы будем вызывать и конструктор типа, не указывая всех параметров, и получать частично применённый конструктор типа. Если мы хотим получить тип для отображений (из модуля Data.Map
) с целочисленными ключами, можно сделать так:
type IntMap v = Map Int v
или так:
type IntMap = Map Int
В любом случае конструктор типов IntMap
принимает один параметр – это и будет типом, в который мы будем отображать Int
.
И вот ещё что. Если вы попытаетесь реализовать этот пример, вам потребуется произвести квалифицированный импорт модуля Data.Map
. При квалифицированном импорте перед конструкторами типов также надо ставить имя модуля. Таким образом, мы бы записали: IntMap = Map.Map Int
.
Убедитесь, что вы понимаете различие между конструкторами типов и конструкторами данных. Если мы создали синоним типа IntMap
или AssocList
, это ещё не означает, что можно делать такие вещи, как AssocList [(1,2),(4,5),(7,9)]
. Это означает только то, что мы можем ссылаться на тип, используя другое имя. Можно написать: [(1,2),(3,5),(8,9)] :: AssocList Int Int
, в результате чего числа в списке будут трактоваться как целые – но мы также сможем работать с этим списком как с обычным списком пар целых чисел. Синонимы типов (и вообще типы) могут использоваться в языке Haskell только при объявлении типов. Часть языка, относящаяся к объявлению типов, – собственно объявление типов (то есть при определении данных и типов) или часть объявления после символа ::
(два двоеточия). Символ ::
используется при декларировании или аннотировании типов.
Интервал:
Закладка: