Scope
Computation-scoped handlers via effect rotation.
handlersFromAttrs
scope.handlersFromAttrs: lift an attrset of handlers, functions, or constants into named effect handlers; preserves shape and state.
handlersFromAttrs : { <name> = handler | (param -> a) | a; ... } -> handlersHelper to transform an attrset into named handlers.
If attrValue is a function { param, state } it is used directly as handler;
If attrValue is a function, resume is f param and preserves state;
Otherwise a constant handler always resumes with attrValue, preserving state.
provide
scope.provide: install stateless handlers for a sub-computation's dynamic extent (reader/val pattern); outer handler state survives unchanged.
scope.provide : handlers -> Computation a -> Computation aInstall handlers for a computation's dynamic extent without touching state. Unhandled effects rotate outward; outer handler state mutations survive unaffected.
This is the reader/val handler pattern (Koka's val, Haskell's
runReader, Scheme's parameterize) — use it when handlers are
stateless (resume with a constant, pass state through).
For handlers that need their own state, use scope.run or
scope.stateful instead.
run
scope.run: handle named effects inside a sub-computation and hide the scope's own state from the caller; rotates unknown effects outward.
scope.run : { handlers, state? } -> Computation a -> Computation aRun a computation with scoped handlers. Effects matching handlers
are handled inside the scope. Unknown effects rotate outward.
The scope's internal state is hidden — caller sees only the body's value.
runWith
scope.runWith: like scope.run but surfaces the scope's final { value, state } to the caller; raw rotation without state hiding.
scope.runWith : { handlers, state? } -> Computation a -> Computation { value, state }Like scope.run but exposes the scope's final state alongside the value.
stateful
scope.stateful: run a sub-computation under scoped handlers while preserving outer state around the rotation point; wraps state.update.
stateful : handlers -> Computation a -> Computation aRun a computation with scoped handlers while preserving state around effect rotation.
val
scope.val: provide constant values as named effect handlers for a sub-computation; sugar for provide (handlersFromAttrs bindings).
scope.val : { <name> = value; ... } -> Computation a -> Computation aProvide constant values as named effect handlers for a computation's dynamic extent. Each key in the bindings attrset becomes an effect that resumes with the corresponding value. Built on scope.provide via handlersFromAttrs.
Named after Koka's val effect handler. For the traditional
single-environment reader (ask/asks/local), see fx.effects.reader.