Skuld.Comp.Env (skuld v0.30.0)
View SourceEnvironment construction and manipulation.
The Env struct carries scope (handlers, leave-scope, transform-suspend)
and effect state. Scope is embedded as a ScopeEnv sub-struct — mutate
through Env.* functions rather than reaching into env.scope directly.
Effect State
Effect state lives exclusively in env.state via put_state/3 and
get_state/2,3. This map is the only state bucket that survives across
fiber suspend/resume cycles — the scheduler threads env.state through
all fibers in a pool.
Do not add arbitrary top-level keys to the %Env{} struct itself.
Such keys will be lost during fiber execution because the scheduler only
preserves scope and state fields. Use put_state/3 for any value
that needs to survive across suspensions.
Summary
Functions
Remove a handler for an effect signature
Get handler for an effect signature (returns nil if missing)
Get handler for an effect signature (raises if missing)
Get the current leave-scope handler (returns identity if nil)
Get the scope sub-struct (for inspection)
Get state for an effect
Get state for an effect, raising if the key is not present (use-after-cleanup guard)
Get the current transform-suspend handler (returns identity if nil)
Get all installed handler signatures
Create a fresh environment with identity leave-scope and transform-suspend
Update state for an effect.
Run the leave-scope chain on a result
Install a handler for an effect signature
Install a new leave-scope handler
Replace the scope sub-struct (for initial construction; prefer with_* functions for mutation)
Install a new transform-suspend handler
Types
@type t() :: %Skuld.Comp.Env{ scope: Skuld.Comp.ScopeEnv.t(), state: %{required(term()) => term()} }
The environment struct.
Fields
scope— scope machinery (evidence, leave_scope, transform_suspend)state— effect state (Writer accumulators, channel state, etc.)
Functions
@spec delete_handler(Skuld.Comp.Types.env(), Skuld.Comp.Types.sig()) :: Skuld.Comp.Types.env()
Remove a handler for an effect signature
@spec get_handler(Skuld.Comp.Types.env(), Skuld.Comp.Types.sig()) :: Skuld.Comp.Types.handler() | nil
Get handler for an effect signature (returns nil if missing)
@spec get_handler!(Skuld.Comp.Types.env(), Skuld.Comp.Types.sig()) :: Skuld.Comp.Types.handler()
Get handler for an effect signature (raises if missing)
@spec get_leave_scope(Skuld.Comp.Types.env()) :: Skuld.Comp.Types.leave_scope()
Get the current leave-scope handler (returns identity if nil)
@spec get_scope(t()) :: Skuld.Comp.ScopeEnv.t()
Get the scope sub-struct (for inspection)
@spec get_state(Skuld.Comp.Types.env(), term(), term()) :: term()
Get state for an effect
@spec get_state!(Skuld.Comp.Types.env(), term()) :: term()
Get state for an effect, raising if the key is not present (use-after-cleanup guard)
@spec get_transform_suspend(t()) :: Skuld.Comp.Types.transform_suspend()
Get the current transform-suspend handler (returns identity if nil)
@spec handler_sigs(Skuld.Comp.Types.env()) :: [Skuld.Comp.Types.sig()]
Get all installed handler signatures
@spec new() :: Skuld.Comp.Types.env()
Create a fresh environment with identity leave-scope and transform-suspend
@spec put_state(Skuld.Comp.Types.env(), term(), term()) :: Skuld.Comp.Types.env()
Update state for an effect.
Effect state lives in env.state — the only map that survives across
fiber suspend/resume cycles. Use module-specific keys (e.g. module attributes
or struct-based keys) to avoid collisions between effects.
See the moduledoc for guidance on what belongs in state vs on the Env
struct directly.
@spec run_leave_scope(Skuld.Comp.Types.env(), term()) :: {Skuld.Comp.Types.result(), Skuld.Comp.Types.env()}
Run the leave-scope chain on a result
@spec with_handler( Skuld.Comp.Types.env(), Skuld.Comp.Types.sig(), Skuld.Comp.Types.handler() ) :: Skuld.Comp.Types.env()
Install a handler for an effect signature
@spec with_leave_scope(Skuld.Comp.Types.env(), Skuld.Comp.Types.leave_scope()) :: Skuld.Comp.Types.env()
Install a new leave-scope handler
@spec with_scope(t(), Skuld.Comp.ScopeEnv.t()) :: t()
Replace the scope sub-struct (for initial construction; prefer with_* functions for mutation)
@spec with_transform_suspend(t(), Skuld.Comp.Types.transform_suspend()) :: t()
Install a new transform-suspend handler