раздел 21
Haskell
Чистые функции, типы как доказательства, ленивость. Учит думать иначе.
Начать раздел
Хочу пройти
Не получилось изменить список. Попробуй ещё раз.
Без входа у каждого урока видно начало. Войди, чтобы читать целиком, отмечать пройденное и решать задачи. войти
Уроки раздела в премиуме: 1 200 ₽ в месяц или 10 000 ₽ в год. Оплата пока не подключена, доступ открывается промокодом. ввести промокод
Мастерская: Интерпретатор lishp
Уроки раздела
Фундамент языка
Иерархия абстракций
Проект 1 · свой Lisp
Изделие «Интерпретатор lishp», крейт lishp
- Архитектура интерпретатора: read, eval, print
- Парсер-комбинаторы с нуля, потом megaparsec
- Ридер: слова в значения, гомоиконность и quote
- Первый eval: диспетчеризация по голове и бинарное ядро
- Ошибки как значения: EvalError и ExceptT
- Спец-формы как значения: quote, eval, car, cdr, cons
- Состояние и окружения: IORef, фреймы, def и set!
- Функции, замыкания, currying и dambda
- Макросы как fexpr: expand-macro и раскрытие до упора
- Стандартная библиотека на самом языке
- Финал: load, CLI на optparse-applicative, REPL на haskeline
Проект 2 · генератор блога
Рантайм и экосистема
Эффекты, трансформеры, type-level
Проект 3 · Servant-бэкенд
Optics и advanced type-level
Functional DDD на Haskell
Эффекты, трансформеры, type-level
Понятия курса
Понятия разобраны внутри уроков. Нажми на понятие, чтобы открыть урок, где оно объясняется.
Фундамент языка
- Выражения, типы и функцииInt/Integer/Double/Char/Bool, кортежи, сигнатуры, каррирование, секции операторов, let и where, вывод типов.урок 2 · Выражения, типы и функцииопираются: урок 3
- Зачем Haskell, GHCup и первая программаЗачем учить Haskell в 2026. GHCup, cabal, HLS, ghci. Первая программа, чистота, ленивость и типы на пальцах. Лямбда-исчисление за 15 минут.урок 1 · Зачем Haskell. GHCup, cabal и первая программаопираются: урок 2
- Списки и рекурсияПаттерн-матчинг, guards, конструирование и разбор списков, аккумуляторы, хвостовая рекурсия, String как [Char].урок 3 · Списки и рекурсияопираются: урок 4, урок 27, урок 33
- Функции высшего порядкаmap/filter/zipWith, лямбды, композиция, `$` и `.`, list comprehensions, бесточечный стиль, экскурсия по Data.List, Data.Char, Data.Function.урок 4 · Функции высшего порядкаопираются: урок 5
- Алгебраические типы и моделирование доменаdata, newtype, type, records, параметризация, Maybe и Either. Невозможные состояния невыразимы, имена это не типобезопасность, smart constructors.урок 6 · Алгебраические типы и моделирование доменаопираются: урок 7, урок 26, урок 27, урок 40, урок 42, урок 51
- Свёртки всерьёзfoldr против foldl против foldl', расстановка скобок, ранний выход, бесконечные списки, какие функции стандартной библиотеки это свёртки.урок 5 · Свёртки всерьёз: foldr, foldl и foldl'опираются: урок 6, урок 8, урок 32
- ТипоклассыКласс, инстанс, deriving, законы. Eq, Ord, Show, Enum, Bounded, иерархия Num. Read как анти-пример. Пишем свой класс.урок 7 · Типоклассы: класс, инстанс, deriving и законыопираются: урок 9, урок 28, урок 30, урок 36, урок 39, урок 40, урок 42
- Ленивость как модель вычисленийРедукция графов, thunk, WHNF против NF, sharing, seq и `$!`, почему foldl течёт, паттерн строгого аккумулятора, первое знакомство со space leak.урок 8 · Модель вычислений: thunk, WHNF и ленивостьопираются: урок 31, урок 32, урок 33
Иерархия абстракций
- Functorfmap и оператор <$>, два закона функтора, функтор это не только контейнер (функции, пары, Either), инстанс руками, композиция функторов.урок 10 · Functor: применить функцию внутри обёрткиопираются: урок 11
- IO и чистое ядроIO как рецепт действия, do для мира, getLine/putStrLn/readFile/writeFile, аргументы командной строки, interact, отделение чистого ядра от грязной оболочки.урок 14 · IO: do для мира и чистое ядроопираются: урок 15, урок 17, урок 18, урок 19, урок 20, урок 21, урок 22, урок 23, урок 24, урок 25, урок 28, урок 29, урок 34, урок 35, урок 37, урок 38, урок 41
- Semigroup и MonoidАссоциативная склейка <> и нейтральный элемент mempty, законы, newtype Sum/Product/Min/Max, mconcat и foldMap, моноиды в конфигурациях и агрегациях.урок 9 · Semigroup и Monoid: склейка с законамиопираются: урок 10, урок 26, урок 30, урок 31
- Applicativepure и <*>, законы, liftA2, аппликативная валидация против монадической (накопление ошибок против короткого замыкания), Alternative с <|>.урок 11 · Applicative: обёрнутая функция и валидацияопираются: урок 12
- Foldable и TraversablefoldMap обобщает свёртки на любой контейнер, sum/length/toList бесплатно, traverse и sequenceA выворачивают слои, обход с эффектом в ежедневном коде.урок 13 · Foldable и Traversable: обход с эффектомопираются: урок 33
- Monadbind >>= и зависимость шага от результата, do-нотация как сахар, три закона, Maybe/Either/список/функция как монады, when/unless/mapM_, где монады заканчиваются.урок 12 · Monad: зависимые шаги и do-нотацияопираются: урок 13, урок 14, урок 16, урок 34, урок 35, урок 37, урок 38, урок 39, урок 41
Проект 1 · свой Lisp
- Архитектура интерпретатора: read, eval, printПетля read, eval, print. Единый тип LishpVal как вселенная данных и кода сразу, тезис "формы это значения", инстанс Show для печати и скелет REPL.урок 15 · Архитектура интерпретатора: read, eval, print
- Первый eval: диспетчеризация по голове и бинарное ядроСамовычисляющиеся значения, список как вызов, диспетчеризация по вычисленной голове. Бинарное ядро BinOp и BinPred, слабая типизация Integer и Double, truthiness и проверка арности.урок 18 · Первый eval: диспетчеризация по голове и бинарное ядро
- Спец-формы как значения: quote, eval, car, cdr, consПочему quote и if нельзя выразить функцией. Диспетчер evalSpecial, помощники на один и два невычисленных аргумента, car, cdr, cons, typeof, do, print, read, symbol.урок 20 · Спец-формы как значения: quote, eval, car, cdr, cons
- Макросы как fexpr: expand-macro и раскрытие до упораТип Macro, проверка на макрос до вычисления аргументов, expandMacro и expandAll, отличие fexpr от Template Haskell и от гигиеничных макросов.урок 23 · Макросы как fexpr: expand-macro и раскрытие до упора
- Ошибки как значения: EvalError и ExceptTТип EvalError с разбором случаев, монада вычислителя ExceptT EvalError IO, throwError и короткое замыкание, читаемые сообщения вместо краха.урок 19 · Ошибки как значения: EvalError и ExceptT
- Парсер-комбинаторы с нуля, потом megaparsecnewtype Parser как функция от входа в Either, инстансы Functor, Applicative, Monad и Alternative, примитив satisfy и выросшие из него many, some, choice, between, sepBy. Потом то же самое на megaparsec.урок 16 · Парсер-комбинаторы с нуля, потом megaparsec
- Ридер: слова в значения, гомоиконность и quoteРазбор атомов, чисел, строк с экранированием, символов и списков на megaparsec. Зарезервированные слова читаются сразу в значения, одинарная кавычка как сокращение для quote, распознавание незавершённого ввода.урок 17 · Ридер: слова в значения, гомоиконность и quote
- Состояние и окружения: IORef, фреймы, def и set!IORef как изменяемая ячейка в чистом языке, тип Env как фрейм плюс ссылка на родителя, def пишет в текущий фрейм, set! идёт по цепочке наружу, REPL с памятью.урок 21 · Состояние и окружения: IORef, фреймы, def и set!
- Стандартная библиотека на самом языкеstd.lsp на самом lishp: бутстрап defmacro и defn, макросы cond, when, and, or, вариадик-обёртки над бинарным ядром, список-библиотека и match через кодогенерацию макросом.урок 24 · Стандартная библиотека на самом языке
- Финал: load, CLI на optparse-applicative, REPL на haskelineСпец-форма load и поиск std.lsp, прогон файлов с общим контекстом, CLI на optparse-applicative, REPL на haskeline с мультилайн-вводом, историей и автодополнением.урок 25 · Финал: load, CLI на optparse-applicative, REPL на haskeline
- Функции, замыкания, каррирование и dambdalambda как код тела плюс захваченное окружение, частичное применение при нехватке аргументов, varargs после точки, трюк def для рекурсии и dambda с динамической областью видимости.урок 22 · Функции, замыкания, currying и dambda
Проект 2 · генератор блога
- Проект как пакет: cabal, Haddock, PVPcabal-файл, библиотека плюс исполняемый файл, модульная структура, Haddock, версии и PVP, что значит выложить на Hackage.урок 29 · Проект как пакет: cabal, Haddock, PVP
- EDSL для HTML: типы как граница безопасностиnewtype Html/Structure/Content, smart-конструкторы, экранирование, экспорт-лист как граница безопасности, Semigroup и Monoid в публичном API.урок 26 · EDSL для HTML: типы как граница безопасности
- Свой парсер разметки без библиотекПострочная рекурсия с одним аккумулятором, тотальная функция parse, sum-тип Document, почему "parse, don't validate".урок 27 · Свой парсер разметки без библиотек
- Склейка: конвертация, обход каталогов и CLIТипокласс ToStructure для конвертации markup в html, чистое ядро process, обход каталога через directory и filepath, ошибки IO в stderr, CLI на optparse-applicative.урок 28 · Склейка: конвертация, обход каталогов и CLI
- Тестирование: hspec, QuickCheck и golden-тестыhspec и table-driven, property-based с QuickCheck (тотальность, round-trip, законы Monoid), golden-тесты на сгенерированный HTML.урок 30 · Тестирование: hspec, QuickCheck и golden-тестыопираются: урок 47
- Строки по-взрослому и производительностьString против Text против ByteString, OverloadedStrings, Builder, конверсии без сюрпризов, criterion-бенчмарк генератора.урок 31 · Строки по-взрослому и производительностьопираются: урок 36
Рантайм и экосистема
- Структуры данных: containers и vectorMap, IntMap, Seq, HashMap и vector: цена операций, персистентность и path copying, stream fusion, когда список это ошибка.урок 33 · Структуры данных: containers и vector
- Исключения и ресурсыОжидаемое кодируй типом, аварийное бросай исключением: Control.Exception, bracket, асинхронные исключения и mask, safe-exceptions.урок 34 · Исключения и ресурсыопираются: урок 37, урок 55
- Конкурентность и STMЗелёные потоки и forkIO, MVar и Chan, STM с retry и orElse, async и структурная конкурентность, сравнение моделей.урок 35 · Конкурентность и STM
- Ленивость в бою: space leaks и профилированиеSpace leaks на реальных примерах, WHNF и deepseq, bang patterns и StrictData, heap-профилирование, бесконечные потоки как фича.урок 32 · Ленивость в боюопираются: урок 36, урок 37
- GHC изнутри: Core, STG и оптимизацииКонвейер понижений parse, rename, typecheck, Core, STG, Cmm. Чтение Core, инлайнинг и unfolding, RULES и fusion, что реально делает -O2.урок 36 · GHC изнутри
Эффекты, трансформеры, type-level
- Reader, Writer, State как паттерныТри монады это одна конструкция с разными инстансами: ниши применения, ловушки ленивого Writer, строгий modify, RWS и что брать в прод.урок 37 · Reader, Writer, State
- Монадные трансформерыСтек эффектов из слоёв: lift и liftIO, распаковка через runX, порядок слоёв меняет семантику, MonadUnliftIO и цена стека.урок 38 · Монадные трансформеры
- Нужна ли тебе эффект-система: зависимости в обычном IOАргументы BurningWitness за обычное IO: явные зависимости, запись функций, bracket и границы гарантий Early.урок 55 · Нужна ли тебе эффект-система: зависимости в обычном IO
- mtl-стиль и ReaderT-паттернКлассы способностей вместо явного стека: MonadReader, MonadState, MonadError, проблема n² инстансов, DefaultSignatures, ReaderT Env IO с has-классами.урок 39 · mtl-стиль и ReaderT-паттернопираются: урок 40, урок 45
- Карта эффект-системFree и freer монады, интерпретаторы, polysemy и effectful, цена программы-значения, мост к Effect.ts и выбор стека для проекта 3.урок 41 · Карта эффект-системопираются: урок 48, урок 55
- Type-level HaskellPhantom types, GADTs, DataKinds, type families, TypeApplications и мини-Servant: тип обработчика вычисляется из типа API. И где остановиться.урок 40 · Type-level Haskellопираются: урок 43, урок 49, урок 50
Проект 3 · Servant-бэкенд
- Архитектура приложения: Env и ReaderTEnv и ReaderT-паттерн, hoistServer и natural transformation, конфигурация, структурированное логирование, доменные ошибки в ServerError.урок 45 · Архитектура приложения: Env и ReaderTопираются: урок 46, урок 47, урок 48, урок 49
- Аутентификация и ролиBasicAuth, generalized auth context, JWT-сессии, роли в прокате: админ клуба против участника.урок 46 · Аутентификация и роли
- База: persistent и esqueletopersistent-схема через QuasiQuotes, миграции, CRUD-запросы, join через esqueleto, compile driven development.урок 44 · База: persistent и esqueleto
- Моделируем домен проката настолокnewtypes и smart constructors для GameId/CopyId/MemberId/DueDate, статусы экземпляра как ADT, aeson-инстансы руками и через Generic.урок 42 · Моделируем домен проката настолокопираются: урок 43, урок 44
- Тестирование сервераhspec-wai, servant-client в тестах, временная БД, property-based на доменных инвариантах, хуки hspec.урок 47 · Тестирование сервера
- Servant: API как типAPI описывается типом, комбинаторы Capture/QueryParam/ReqBody, Handler, какая type-level механика это обслуживает, servant-client бесплатно.урок 43 · Servant: API как типопираются: урок 45, урок 50
- В прод: Docker, миграции, метрикиMulti-stage Docker и статический бинарь, healthcheck, миграции при деплое, метрики и куда смотреть. Факультатив: тот же сервис на effectful.урок 48 · В прод: Docker, миграции, метрики
Optics и advanced type-level
- Advanced type-levelClosed и open type families, TypeFamilyDependencies, GHC.Generics изнутри, singletons и dependent Haskell teaser, разбираем кусок внутренностей Servant.урок 50 · Advanced type-level
- Optics: Lens, Prism, TraversalLens, Prism, Traversal и их законы, van Laarhoven-кодировка на пальцах, generic-lens, пакет lens против optics, рефакторим доступ к Env проекта 3.урок 49 · Optics: Lens, Prism, Traversal
Functional DDD на Haskell
- Доменные типы на HaskellNewtype как номинальный тип, скрытый конструктор данных и список экспорта как граница доверия, smart-конструкторы mkX, инварианты DateRange и Money, ValueError как канал отказа, FromJSON через парсинг.урок 51 · Доменные типы на Haskell: newtype, скрытый конструктор, smart-конструкторыопираются: урок 52
- Decider на HaskellКоманды против событий, внутренне-тегированный JSON событий, состояние как сумма типов, Decider записью функций вместо класса типов, чистая decide с явным Timestamp, тотальная evolve, replay через foldl и его закон под QuickCheck, BDD-сценарии на hspec.урок 52 · Decider на Haskell: decide, evolve, replay и явное времяопираются: урок 53
- Event store на PostgresAppend-only журнал, контракт EventStore записью функций, оптимистичная блокировка на версии стрима, in-memory реализация на STM с broadcast-каналом, схема с unique (stream_id, version), postgresql-simple без Template Haskell, SQLSTATE 23505 как ConcurrencyConflict.урок 53 · Event store на Postgres: STM, postgresql-simple, оптимистичная блокировкаопираются: урок 54
- Проекции и CQRS на STMCQRS, проекция как чистый фолд с собственным контекстом pending, живой поток на forkIO поверх подписки, снимок в TVar, ожидание через STM retry без опроса, eventual consistency и пересборка read-модели, итог трека Functional DDD.урок 54 · Проекции и CQRS на STM: чистый фолд, forkIO, снимок в TVar