Теория категорий

Монады

async/await в JavaScript, Option в Rust, Result в Go - это одна математическая абстракция, изобретённая в теории категорий. Понять монаду - значит разом понять структуру управления ошибками и асинхронности в любом современном языке.

  • JavaScript: Promise (.then = bind) - монада в 99% веб-приложений
  • Rust: Option и Result - монадическая обработка ошибок без исключений
  • Haskell: IO-монада - весь GHC и промышленный код через монады
  • Scala ZIO: effect system для финтех-бэкендов в production
  • TypeScript: fp-ts - монады в фронтенде, 3M загрузок/месяц
  • Kotlin Arrow: монады в Android SDK, корутины - монадический паттерн

Монада: моноид в категории эндофункторов

Async/await в JavaScript, Option в Rust, Result в Haskell, Promise в TypeScript - это всё монады. Одна математическая абстракция покрывает три языка, пять парадигм. Понимание монад означает понимание структуры любого из этих механизмов.

Монада на категории C - это тройка (T, eta, mu), где T: C -> C - эндофунктор, eta: Id => T - единица (return), mu: T^2 => T - умножение (join). Три диаграммы должны коммутировать: ассоциативность и два единичных закона. Это в точности структура моноида - но в категории эндофункторов.

Почему говорят 'монада - это моноид в категории эндофункторов'? Что играет роль единицы и умножения моноида?

Законы монады и категория Клейсли

Законы монады через bind (>>=) формулируются так: левое тождество (return a >>= f = f a), правое тождество (m >>= return = m), ассоциативность ((m >>= f) >>= g = m >>= (x -> f x >>= g)). Это в точности законы категории Клейсли.

Категория Клейсли C_T имеет те же объекты, что C, но морфизмы A -> B - это стрелки A -> T(B) в C. Состав Клейсли: f: A -> T(B), g: B -> T(C) компонуются через bind. Это абстрактная модель цепочки вычислений с эффектами.

Promise в JavaScript - монада. `.then()` = bind, `Promise.resolve()` = return/eta. Техническое уточнение: Promise нарушает один закон (Promise.resolve(Promise.resolve(x)) === Promise.resolve(x) из-за автофлаттена), но на практике это экономит код. Rust's `?` оператор - синтаксический сахар над Result монадой.

Объясните, как закон ассоциативности монады (m >>= f) >>= g = m >>= (x -> f x >>= g) связан с ассоциативностью в категории Клейсли.

Maybe, List, IO, State: четыре монады в деталях

Каждая монада кодирует определённый вид вычислительного эффекта. Maybe - частичность (возможность отсутствия результата). List - недетерминированность (несколько результатов). IO - реальные побочные эффекты. State - изменяемое состояние без мутации.

В Haskell весь IO происходит через IO монаду. main :: IO () - это значение монадического типа, описание программы. Запускает его рантайм. Это не трюк - это категориальный способ разделить описание программы и её выполнение. GHC выводит 40+ оптимизаций именно потому, что знает структуру монад.

List монада моделирует недетерминированность. Как bind для List реализует 'выбор' между ветвями? Что произойдёт, если в середине цепочки вернуть пустой список?

Ключевые идеи

  • Монада = эндофунктор T + eta (return) + mu (join), удовлетворяющие ассоциативности и единичным законам
  • Монада = моноид в категории эндофункторов: mu - умножение, eta - единица
  • Категория Клейсли: морфизмы A -> T(B) с bind как композицией; законы монады = аксиомы категории
  • Maybe - частичность; List - недетерминированность; IO - эффекты; State - состояние; Writer - логирование
  • Promise (.then = bind), Option (Rust), ? operator - конкретные монады в production коде

Связанные темы

Монады объединяют функторы, естественные преобразования и сопряжения.

  • Теория категорий в индустрии — Функторы и естественные преобразования - строительные блоки монад
  • Сопряжённые функторы — Каждое сопряжение F - G порождает монаду G.F

Связанные уроки

  • plt-30-io-monads
  • plt-31-algebraic-effects
Монады

0

1

Войти