Теория языков программирования
Алгебраические эффекты
async/await - это algebraic effect. Exceptions - algebraic effect. State - algebraic effect. Algebraic effects - единый механизм, объединяющий то, что раньше требовало разных языковых фич.
- **OCaml 5.0**: algebraic effects как основа нового Domain-based parallelism. Jane Street (trading firm) использует OCaml в продакшене - это не академика
- **async/await в Kotlin**: coroutines реализованы через CPS transformation - это algebraic effect Async на уровне компилятора
- **WebAssembly Effect Handlers**: WasmGC + effect handlers proposal - следующая версия Wasm получит algebraic effects для управления GC и concurrency
Effect Handlers
Algebraic effects - механизм, где код объявляет эффекты (операции), а обработчик (handler) выше в стеке определяет их семантику. Это разделение: код описывает что делать (perform Effect), handler решает как (with handle). Элегантнее монад для многих задач.
Algebraic effects = extensible effects. Монады для State, Maybe, IO требуют monad transformers для комбинирования. Effects комбинируются бесплатно - просто добавляешь нужный эффект в сигнатуру функции.
В чём принципиальное отличие algebraic effects от монад?
Resumable Computations
Ключевая особенность algebraic effects: вычисление может быть приостановлено при выполнении эффекта, и handler может возобновить его (`resume`) с результатом. Это первоклассные continuations с ограниченной областью видимости - delimited continuations.
Как algebraic effects позволяют одному и тому же коду работать и синхронно, и асинхронно?
Koka
Koka - язык от Microsoft Research, где algebraic effects встроены в систему типов первоклассно. Тип функции включает её эффекты: `fun f() : <State<Int>, Async> String`. Компилятор проверяет что все эффекты обработаны.
Что означает тип `fun f() : <State<Int>, Async, Raise> String` в Koka?
Unison
Unison - язык с algebraic effects как основой concurrency модели. Abilities (термин Unison для effects) + fiber-based runtime. Ключевая идея: код идентифицируется своим хешем (content-addressed), а не именем файла.
OCaml 5 (2022) добавил algebraic effects как первоклассную фичу для реализации concurrent runtime. Effect handlers - основа нового eio (effect-based IO) фреймворка для OCaml.
Algebraic effects - академическая концепция без практического применения
OCaml 5 (production язык Jane Street), Koka (Microsoft Research), Unison уже используют algebraic effects. async/await в JS - частный случай эффектов
async/await - это algebraic effect Async без явной системы типов. Effect handlers - обобщение, которое позволяет строить async, exceptions, state, non-determinism единообразно
Как algebraic effects упрощают тестирование по сравнению с монадами?
Итоги
- **Algebraic effects**: код выполняет операцию (perform), handler выше в стеке определяет её семантику. Разделение what и how
- **Resumable**: handler может возобновить вычисление через resume(value). Первоклассные delimited continuations
- **Koka**: effects в системе типов. Тип функции включает все эффекты - compile-time проверка
- **Unison/OCaml 5**: production языки с algebraic effects. async/await = algebraic effect без явной системы эффектов
Связанные темы
Algebraic effects обобщают многие механизмы:
- IO монады — IO монада - менее гибкая альтернатива для управления side effects
- Async/await и coroutines — Async/await - специальный случай effect handler для Async эффекта
Вопросы для размышления
- async/await в JavaScript - это algebraic effect. Почему тогда async 'заражает' всю цепочку вызовов (функция вызывающая async становится async)? Algebraic effects решают эту проблему?
- Algebraic effects позволяют тестировать без моков - тестовый handler подменяет production. Как это меняет архитектуру приложения по сравнению с Dependency Injection?
- OCaml 5 добавил effects для multicore parallelism. Как effects помогают построить scheduler который не блокирует OS thread при IO операции?