
Полная версия
Курс Хаскель от джуна до мидла
:browse — показать содержимое модуля
:main — запустить main
:set — установить опции
:unset — сбросить опции
:show bindings — показать определённые имена
:show modules — показать загруженные модули
:show packages — показать пакеты
:def — определить макрос
:undef — удалить макрос
:cd — сменить директорию
:edit — открыть редактор
:etags — сгенерировать tags
:ctags — сгенерировать ctags
Примеры использования :kind:
:k Maybe — * -> *
:k Either — * -> * -> *
:k Int — *
2.13. Создание и использование .ghci файла
Пример ~/.ghci:
:set prompt "λ> "
:set prompt-cont "λ| "
:set +t
:set -Wall
:set -XOverloadedStrings
:set -XFlexibleContexts
:set -XTypeApplications
:def hoogle \x -> return $ ":!hoogle " ++ x
:def docs \x -> return $ ":!hoogle --info " ++ x
Теперь можно писать:
λ> :hoogle map
λ> :docs fmap
2.14. Работа с Cabal (базовый workflow)
cabal init --interactive
cabal build
cabal run
cabal test
cabal repl -- GHCi с зависимостями проекта
cabal install --lib some-package
cabal update
cabal freeze -- зафиксировать версии
cabal outdated
2.15. Stack workflow
stack new project-name
stack build
stack exec project-name-exe
stack test
stack ghci
stack install
stack upgrade
Многие разработчики в 2020-х предпочитают cabal + ghcup, но stack всё ещё популярен благодаря snapshot'ам Stackage.
ГЛАВА 3. РАСШИРЕННЫЙ МАТЕРИАЛ: ТИПЫ И СИНТАКСИС
3.14. Подробно о числовых типах
Int — минимум ±2^29, обычно ±2^63
Int8, Int16, Int32, Int64
Word, Word8 ... Word64 — беззнаковые
Integer — произвольная точность
Float, Double
Rational — точные дроби (Ratio Integer)
Complex Double
Преобразования:
fromIntegral :: (Integral a, Num b) => a -> b
realToFrac :: (Real a, Fractional b) => a -> b
fromInteger :: Num a => Integer -> a
toInteger :: Integral a => a -> Integer
3.15. Подробно о логических операциях и сравнениях
(&&) || not
== /= < > <= >=
compare :: Ord a => a -> a -> Ordering -- LT | EQ | GT
min, max
3.16. Ещё примеры с where и let
-- Вычисление корней квадратного уравнения
quadratic a b c
| disc < 0 = Nothing
| otherwise = Just (x1, x2)
where
disc = b*b - 4*a*c
sqrtDisc = sqrt disc
x1 = (-b + sqrtDisc) / (2*a)
x2 = (-b - sqrtDisc) / (2*a)
-- let в выражениях
let result = let x = 10
y = 20
in x * y + 5
in result
3.17. Большое количество упражнений
1. Напишите функцию isTriangle a b c.
2. Напишите функцию isRightTriangle a b c (проверка теоремы Пифагора).
3. Реализуйте функцию clamp low high value.
4. Напишите функцию, которая возвращает строку "Fizz", "Buzz", "FizzBuzz" или число (классическая задача).
5. Создайте функцию, форматирующую число секунд в "Dd Hh Mm Ss".
6. Напишите функцию, вычисляющую расстояние между двумя точками на плоскости.
7. Реализуйте функцию, определяющую квадрант точки.
8. Напишите функцию, которая по году возвращает век.
ГЛАВА 4. РАСШИРЕННЫЙ ПРАКТИЧЕСКИЙ МАТЕРИАЛ И ПРИМЕРЫ
Ниже приведены дополнительные подробные примеры, разборы типичных ошибок и упражнения повышенной сложности для главы 4.
Примеры кода:
-- Пример 1
example1 :: [Int] -> Int
example1 xs = foldr (+) 0 (map (^2) (filter even xs))
-- Пример 2
example2 :: Maybe Int -> Maybe Int -> Maybe Int
example2 mx my = do
x <- mx
y <- my
return (x + y)
-- Пример 3
example3 :: Either String Int -> Either String Int
example3 e = case e of
Left err -> Left ("Ошибка: " ++ err)
Right n -> Right (n * 2)
-- Пример 4 (рекурсия)
example4 :: [a] -> [a]
example4 [] = []
example4 [x] = [x]
example4 (x:y:xs) = y : x : example4 xs
-- Пример 5 (высшие функции)
example5 :: (a -> Bool) -> [a] -> [a]
example5 p = foldr (\x acc -> if p x then x:acc else acc) []
Типичные ошибки новичков в этой теме:
• Забывают, что паттерн-матчинг идёт сверху вниз.
• Путают foldl и foldr.
• Пытаются использовать изменяемые переменные.
• Игнорируют предупреждения компилятора.
• Пишут слишком общие типы там, где нужны конкретные.
• Злоупотребляют partial-функциями (head, tail, !!, fromJust).
Советы по стилю:
• Давайте функциям говорящие имена.
• Добавляйте type signatures почти везде.
• Разбивайте сложные функции на маленькие.
• Используйте where для вспомогательных определений.
• Предпочитайте тотальные функции.
Упражнения повышенной сложности:
1. Реализуйте функцию, которая принимает список и возвращает список всех его подсписков (powersets).
2. Напишите функцию groupBy с кастомным компаратором равенства.
3. Реализуйте собственную версию mapAccumL / mapAccumR.
4. Создайте функцию, которая безопасно достаёт элемент по индексу и возвращает Maybe.
5. Напишите функцию, которая разбивает список на куски фиксированного размера (chunksOf).
6. Реализуйте zipWith3, zipWith4 через рекурсию или fold.
7. Напишите функцию, которая находит все позиции вхождения элемента в список.
8. Создайте функцию unique, сохраняющую порядок первого вхождения.
9. Реализуйте intersperse и intercalate самостоятельно.
10. Напишите функцию, которая проверяет, является ли один список подсписком другого.
Дополнительные рассуждения:
При работе с этой темой важно постоянно спрашивать себя:
- Можно ли сделать эту функцию тотальной?
- Можно ли выразить её через уже существующие высшие функции?
- Насколько легко её тестировать?
- Хорошо ли читается point-free версия или лучше оставить явные аргументы?
Чем больше вы практикуетесь, тем быстрее начинаете "видеть" решения в терминах map / filter / fold / unfold / traverse.
ГЛАВА 5. РАСШИРЕННЫЙ ПРАКТИЧЕСКИЙ МАТЕРИАЛ И ПРИМЕРЫ
Ниже приведены дополнительные подробные примеры, разборы типичных ошибок и упражнения повышенной сложности для главы 5.
Примеры кода:
-- Пример 1
example1 :: [Int] -> Int
example1 xs = foldr (+) 0 (map (^2) (filter even xs))
-- Пример 2
example2 :: Maybe Int -> Maybe Int -> Maybe Int
example2 mx my = do
x <- mx
y <- my
return (x + y)
-- Пример 3
example3 :: Either String Int -> Either String Int
example3 e = case e of
Left err -> Left ("Ошибка: " ++ err)
Right n -> Right (n * 2)
-- Пример 4 (рекурсия)
example4 :: [a] -> [a]
example4 [] = []
example4 [x] = [x]
example4 (x:y:xs) = y : x : example4 xs
-- Пример 5 (высшие функции)
example5 :: (a -> Bool) -> [a] -> [a]
example5 p = foldr (\x acc -> if p x then x:acc else acc) []
Типичные ошибки новичков в этой теме:
• Забывают, что паттерн-матчинг идёт сверху вниз.
• Путают foldl и foldr.
• Пытаются использовать изменяемые переменные.
• Игнорируют предупреждения компилятора.
• Пишут слишком общие типы там, где нужны конкретные.
• Злоупотребляют partial-функциями (head, tail, !!, fromJust).
Советы по стилю:
• Давайте функциям говорящие имена.
• Добавляйте type signatures почти везде.
• Разбивайте сложные функции на маленькие.
• Используйте where для вспомогательных определений.
• Предпочитайте тотальные функции.
Упражнения повышенной сложности:
1. Реализуйте функцию, которая принимает список и возвращает список всех его подсписков (powersets).
2. Напишите функцию groupBy с кастомным компаратором равенства.
3. Реализуйте собственную версию mapAccumL / mapAccumR.
4. Создайте функцию, которая безопасно достаёт элемент по индексу и возвращает Maybe.
5. Напишите функцию, которая разбивает список на куски фиксированного размера (chunksOf).
6. Реализуйте zipWith3, zipWith4 через рекурсию или fold.
7. Напишите функцию, которая находит все позиции вхождения элемента в список.
8. Создайте функцию unique, сохраняющую порядок первого вхождения.
9. Реализуйте intersperse и intercalate самостоятельно.
10. Напишите функцию, которая проверяет, является ли один список подсписком другого.
Дополнительные рассуждения:
При работе с этой темой важно постоянно спрашивать себя:
- Можно ли сделать эту функцию тотальной?
- Можно ли выразить её через уже существующие высшие функции?
- Насколько легко её тестировать?
- Хорошо ли читается point-free версия или лучше оставить явные аргументы?
Чем больше вы практикуетесь, тем быстрее начинаете "видеть" решения в терминах map / filter / fold / unfold / traverse.
ГЛАВА 6. РАСШИРЕННЫЙ ПРАКТИЧЕСКИЙ МАТЕРИАЛ И ПРИМЕРЫ
Ниже приведены дополнительные подробные примеры, разборы типичных ошибок и упражнения повышенной сложности для главы 6.
Примеры кода:
-- Пример 1
example1 :: [Int] -> Int
example1 xs = foldr (+) 0 (map (^2) (filter even xs))
-- Пример 2
example2 :: Maybe Int -> Maybe Int -> Maybe Int
example2 mx my = do
x <- mx
y <- my
return (x + y)
Конец ознакомительного фрагмента.
Текст предоставлен ООО «Литрес».
Прочитайте эту книгу целиком, купив полную легальную версию на Литрес.
Безопасно оплатить книгу можно банковской картой Visa, MasterCard, Maestro, со счета мобильного телефона, с платежного терминала, в салоне МТС или Связной, через PayPal, WebMoney, Яндекс.Деньги, QIWI Кошелек, бонусными картами или другим удобным Вам способом.









