Теория категорий
Монады
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