Изучай Haskell во имя добра! - Миран Липовача
0/0

Изучай Haskell во имя добра! - Миран Липовача

Уважаемые читатели!
Тут можно читать бесплатно Изучай Haskell во имя добра! - Миран Липовача. Жанр: Программирование. Так же Вы можете читать полную версию (весь текст) онлайн книги без регистрации и SMS на сайте Knigi-online.info (книги онлайн) или прочесть краткое содержание, описание, предисловие (аннотацию) от автора и ознакомиться с отзывами (комментариями) о произведении.
Описание онлайн-книги Изучай Haskell во имя добра! - Миран Липовача:
На взгляд автора, сущность программирования заключается в решении проблем. Программист всегда думает о проблеме и возможных решениях – либо пишет код для выражения этих решений.Язык Haskell имеет множество впечатляющих возможностей, но главное его свойство в том, что меняется не только способ написания кода, но и сам способ размышления о проблемах и возможных решениях. Этим Haskell действительно отличается от большинства языков программирования. С его помощью мир можно представить и описать нестандартным образом. И поскольку Haskell предлагает совершенно новые способы размышления о проблемах, изучение этого языка может изменить и стиль программирования на всех прочих.Ещё одно необычное свойство Haskell состоит в том, что в этом языке придаётся особое значение рассуждениям о типах данных. Как следствие, вы помещаете больше внимания и меньше кода в ваши программы.Вне зависимости от того, в каком направлении вы намерены двигаться, путешествуя в мире программирования, небольшой заход в страну Haskell себя оправдает. А если вы решите там остаться, то наверняка найдёте чем заняться и чему поучиться!Эта книга поможет многим читателям найти свой путь к Haskell.Отображения, монады, моноиды и другое!Всё сказано в названии: «Изучай Хаскель во имя добра!» – весёлый иллюстрированный самоучитель по этому сложному функциональному языку.С помощью оригинальных рисунков автора, отсылке к поп-культуре, и, самое главное, благодаря полезным примерам кода, эта книга обучает основам функционального программирования так, как вы никогда не смогли бы себе представить.Вы начнете изучение с простого материала: основы синтаксиса, рекурсия, типы и классы типов. Затем, когда вы преуспеете в основах, начнется настоящий мастер-класс от профессионала: вы изучите, как использовать аппликативные функторы, монады, застежки, и другие легендарные конструкции Хаскеля, о которых вы читали только в сказках.Продираясь сквозь образные (и порой безумные) примеры автора, вы научитесь:• Смеяться в лицо побочным эффектам, поскольку вы овладеете техниками чистого функционального программирования.• Использовать волшебство «ленивости» Хаскеля для игры с бесконечными наборами данных.• Организовывать свои программы, создавая собственные типы, классы типов и модули.• Использовать элегантную систему ввода-вывода Хаскеля, чтобы делиться гениальностью ваших программ с окружающим миром.Нет лучшего способа изучить этот мощный язык, чем чтение «Изучай Хаскель во имя добра!», кроме, разве что, поедания мозга его создателей.Миран Липовача (Miran Lipovača) изучает информатику в Любляне (Словения). Помимо его любви к Хаскелю, ему нравится заниматься боксом, играть на бас-гитаре и, конечно же, рисовать. У него есть увлечение танцующими скелетами и числом 71, а когда он проходит через автоматические двери, он притворяется, что на самом деле открывает их силой своей мысли.

Аудиокнига "Изучай Haskell во имя добра!"



📚 Хотите погрузиться в мир функционального программирования и освоить новый язык программирования? Тогда аудиокнига "Изучай Haskell во имя добра!" от автора Мирана Липовача - это то, что вам нужно!



Главный герой книги, начинающий программист, отправляется в увлекательное путешествие по Haskell, чтобы понять его принципы и особенности. Слушая эту аудиокнигу, вы узнаете, как создавать функциональные программы, работать с типами данных, рекурсией и многим другим.



Автор книги, Миран Липовач, является экспертом в области функционального программирования и преподавателем. Он делится своими знаниями и опытом, помогая слушателям легко освоить новый язык программирования.



На сайте knigi-online.info вы можете бесплатно и без регистрации слушать аудиокниги на русском языке. Здесь собраны бестселлеры и лучшие произведения различных жанров, включая программирование.



Не упустите возможность познакомиться с увлекательным миром Haskell и функционального программирования через аудиокнигу "Изучай Haskell во имя добра!" от Мирана Липовача. Погрузитесь в новые знания и расширьте свой кругозор!



Погрузитесь в мир программирования с категорией аудиокниг: Программирование.

Читем онлайн Изучай Haskell во имя добра! - Миран Липовача

Шрифт:

-
+

Интервал:

-
+

Закладка:

Сделать
1 ... 77 78 79 80 81 82 83 84 85 ... 96

Поскольку значение, возвращаемое функцией addDrink, является кортежем типа (Food,Price), мы можем передать этот результат функции addDrink ещё раз, чтобы функция сообщила нам, какой напиток будет подан в сопровождение к блюду и сколько это нам будет стоить. Давайте попробуем:

ghci> ("собачатина", Sum 5) `applyLog` addDrink `applyLog` addDrink

("пиво",Sum {getSum = 65})

Добавление напитка к какой-нибудь там собачатине вернёт пиво и дополнительные 30 центов, то есть ("пиво", Sum 35). А если мы используем функцию applyLog для передачи этого результата функции addDrink, то получим ещё одно пиво, и результатом будет ("пиво", Sum 65).

Тип Writer

Теперь, когда мы увидели, что значение с присоединённым моноидом ведёт себя как монадическое значение, давайте исследуем экземпляр класса Monad для типов таких значений. Модуль Control.Monad.Writer экспортирует тип Writer w a со своим экземпляром класса Monad и некоторые полезные функции для работы со значениями такого типа.

Прежде всего, давайте исследуем сам тип. Для присоединения моноида к значению нам достаточно поместить их в один кортеж. Тип Writer w a является просто обёрткой newtype для кортежа. Его определение несложно:

newtype Writer w a = Writer { runWriter :: (a, w) }

Чтобы кортеж мог быть сделан экземпляром класса Monad и его тип был отделён от обычного кортежа, он обёрнут в newtype. Параметр типа a представляет тип значения, параметр типа w – тип присоединённого значения моноида.

Экземпляр класса Monad для этого типа определён следующим образом:

instance (Monoid w) => Monad (Writer w) where

   return x = Writer (x, mempty)

   (Writer (x,v)) >>= f = let (Writer (y, v')) = f x

                          in Writer (y, v `mappend` v')

Во-первых, давайте рассмотрим операцию >>=. Её реализация по существу аналогична функции applyLog, только теперь, поскольку наш кортеж обёрнут в тип newtype Writer, мы должны развернуть его перед сопоставлением с образцом. Мы берём значение x и применяем к нему функцию f. Это даёт нам новое значение Writer w a, и мы используем выражение let для сопоставления его с образцом. Представляем y в качестве нового результата и используем функцию mappend для объединения старого моноидного значения с новым. Упаковываем его вместе с результирующим значением в кортеж, а затем оборачиваем с помощью конструктора Writer, чтобы нашим результатом было значение Writer, а не просто необёрнутый кортеж.

Ладно, а что у нас с функцией return? Она должна принимать значение и помещать его в минимальный контекст, который по-прежнему возвращает это значение в качестве результата. Так каким был бы контекст для значений типа Writer? Если мы хотим, чтобы сопутствующее моноидное значение оказывало на другие моноидные значения наименьшее влияние, имеет смысл использовать функцию mempty. Функция mempty используется для представления «единичных» моноидных значений, как, например, "", Sum 0 и пустые строки байтов. Когда мы выполняем вызов функции mappend между значением mempty и каким-либо другим моноидным значением, результатом будет это второе моноидное значение. Так что если мы используем функцию return для создания значения монады Writer, а затем применяем оператор >>= для передачи этого значения функции, окончательным моноидным значением будет только то, что возвращает функция. Давайте используем функцию return с числом 3 несколько раз, только каждый раз будем соединять его попарно с другим моноидом:

ghci> runWriter (return 3 :: Writer String Int)

(3,"")

ghci> runWriter (return 3 :: Writer (Sum Int) Int)

(3,Sum {getSum = 0})

ghci> runWriter (return 3 :: Writer (Product Int) Int)

(3,Product {getProduct = 1})

Поскольку у типа Writer нет экземпляра класса Show, нам пришлось использовать функцию runWriter для преобразования наших значений типа Writer в нормальные кортежи, которые могут быть показаны в виде строки. Для строк единичным значением является пустая строка. Для типа Sum это значение 0, потому что если мы прибавляем к чему-то 0, это что-то не изменяется. Для типа Product единичным значением является 1.

В экземпляре класса Monad для типа Writer не имеется реализация для функции fail; значит, если сопоставление с образцом в нотации do оканчивается неудачно, вызывается функция error.

Использование нотации do с типом Writer

Теперь, когда у нас есть экземпляр класса Monad, мы свободно можем использовать нотацию do для значений типа Writer. Это удобно, когда у нас есть несколько значений типа Writer и мы хотим с ними что-либо делать. Как и в случае с другими монадами, можно обрабатывать их как нормальные значения, и контекст сохраняется для нас. В этом случае все моноидные значения, которые идут в присоединённом виде, объединяются с помощью функции mappend, а потому отражаются в окончательном результате. Вот простой пример использования нотации do с типом Writer для умножения двух чисел:

import Control.Monad.Writer

logNumber :: Int –> Writer [String] Int

logNumber x = Writer (x, ["Получено число: " ++ show x])

multWithLog :: Writer [String] Int

multWithLog = do

   a <– logNumber 3

   b <– logNumber 5

   return (a*b)

Функция logNumber принимает число и создаёт из него значение типа Writer. Для моноида мы используем список строк и снабжаем число одноэлементным списком, который просто говорит, что мы получили это число. Функция multWithLog – это значение типа Writer, которое перемножает 3 и 5 и гарантирует включение прикреплённых к ним журналов в окончательный журнал. Мы используем функцию return, чтобы вернуть значение (a*b) в качестве результата. Поскольку функция return просто берёт что-то и помещает в минимальный контекст, мы можем быть уверены, что она ничего не добавит в журнал. Вот что мы увидим, если выполним этот код:

ghci> runWriter multWithLog

(15,["Получено число: 3","Получено число: 5"])

Добавление в программы функции журналирования

Иногда мы просто хотим, чтобы некое моноидное значение было включено в каком-то определённом месте. Для этого может пригодиться функция tell. Она является частью класса типов MonadWriter и в случае с типом Writer берёт монадическое значение вроде ["Всё продолжается"] и создаёт значение типа Writer, которое возвращает значение-пустышку () в качестве своего результата, но прикрепляет желаемое моноидное значение. Когда у нас есть монадическое значение, которое в качестве результата содержит значение (), мы не привязываем его к переменной. Вот определение функции multWithLog с включением некоторых дополнительных сообщений:

multWithLog :: Writer [String] Int

multWithLog = do

   a <– logNumber 3

   b <– logNumber 5

   tell ["Перемножим эту парочку"]

   return (a*b)

Важно, что вызов return (a*b) находится в последней строке, потому что результат последней строки в выражении do является результатом всего выражения do. Если бы мы поместили вызов функции tell на последнюю строку, результатом этого выражения do было бы (). Мы бы потеряли результат умножения. Однако журнал остался бы прежним. Вот функция в действии:

ghci> runWriter multWithLog

(15,["Получено число: 3","Получено число: 5","Перемножим эту парочку"])

Добавление журналирования в программы

Алгоритм Евклида – это алгоритм, который берёт два числа и вычисляет их наибольший общий делитель, то есть самое большое число, на которое делятся без остатка оба числа. В языке Haskell уже имеется функция gcd, которая проделывает это, но давайте реализуем её сами, а затем снабдим её возможностями журналирования. Вот обычный алгоритм:

gcd' :: Int –> Int –> Int

gcd' a b

   | b == 0 = a

   | otherwise = gcd' b (a `mod` b)

Алгоритм очень прост. Сначала он проверяет, равно ли второе число 0. Если равно, то результатом становится первое число. Если не равно, то результатом становится наибольший общий делитель второго числа и остаток от деления первого числа на второе. Например, если мы хотим узнать, каков наибольший общий делитель 8 и 3, мы просто следуем изложенному алгоритму. Поскольку 3 не равно 0, мы должны найти наибольший общий делитель 3 и 2 (если мы разделим 8 на 3, остатком будет 2). Затем ищем наибольший общий делитель 3 и 2. Число 2 по-прежнему не равно 0, поэтому теперь у нас есть 2 и 1. Второе число не равно 0, и мы выполняем алгоритм ещё раз для 1 и 0, поскольку деление 2 на 1 даёт нам остаток равный 0. И наконец, поскольку второе число равно 0, финальным результатом становится 1. Давайте посмотрим, согласуется ли наш код:

1 ... 77 78 79 80 81 82 83 84 85 ... 96
На этой странице вы можете бесплатно читать книгу Изучай Haskell во имя добра! - Миран Липовача бесплатно.

Оставить комментарий

Рейтинговые книги