Skuld.Effects.State (skuld v0.23.0)
View SourceState effect - mutable state threaded through computation.
Supports both simple single-state usage and multiple independent states via tags.
Simple Usage (default tag)
use Skuld.Syntax
alias Skuld.Effects.State
comp do
n <- State.get()
_ <- State.put(n + 1)
n
end
|> State.with_handler(0)
|> Comp.run!()
#=> 0Multiple States (explicit tags)
comp do
_ <- State.put(:counter, 0)
_ <- State.modify(:counter, &(&1 + 1))
count <- State.get(:counter)
_ <- State.put(:name, "alice")
name <- State.get(:name)
{count, name}
end
|> State.with_handler(0, tag: :counter)
|> State.with_handler("", tag: :name)
|> Comp.run!()
#=> {1, "alice"}Per-tag dispatch
Each tag gets its own handler sig (a module atom) and compact operation atoms. The tag is encoded in the sig, not in the operation args, so operations carry only the data they need:
get→Comp.effect(sig, State.Get)— bare atom, zero allocationput→Comp.effect(sig, {State.Put, value})— minimal 2-tuple
Summary
Functions
Install State handler via catch clause syntax.
Returns the get operation atom.
Extract the state for the given tag from an env
Get a value derived from the state.
Modify the state with a function, returning the old value.
Returns the put operation atom.
Returns the env.state key used for a given tag.
Install a scoped State handler for a computation.
Functions
Install State handler via catch clause syntax.
Accepts either initial or {initial, opts}:
catch
State -> 0 # initial value
State -> {0, output: fn r, s -> {r, s} end} # with opts
@spec get_op() :: atom()
Returns the get operation atom.
@spec get_state(Skuld.Comp.Types.env(), atom()) :: term()
Extract the state for the given tag from an env
@spec gets((term() -> term())) :: Skuld.Comp.Types.computation()
Get a value derived from the state.
Examples
State.gets(&Map.get(&1, :name)) # use default tag
State.gets(:user, &Map.get(&1, :name)) # use explicit tag
@spec gets(atom(), (term() -> term())) :: Skuld.Comp.Types.computation()
@spec modify((term() -> term())) :: Skuld.Comp.Types.computation()
Modify the state with a function, returning the old value.
Examples
State.modify(&(&1 + 1)) # use default tag
State.modify(:counter, &(&1 + 1)) # use explicit tag
@spec modify(atom(), (term() -> term())) :: Skuld.Comp.Types.computation()
@spec put_op() :: atom()
Returns the put operation atom.
Returns the env.state key used for a given tag.
Useful for configuring EffectLogger's state_keys filter.
Examples
# Only capture State effect data in EffectLogger snapshots
EffectLogger.with_logging(state_keys: [State.state_key(MyApp.Counter)])
# Multiple states
EffectLogger.with_logging(state_keys: [
State.state_key(:counter),
State.state_key(:user)
])
@spec with_handler(Skuld.Comp.Types.computation(), term(), keyword()) :: Skuld.Comp.Types.computation()
Install a scoped State handler for a computation.
Options
tag- the state tag (default:Skuld.Effects.State)output- optional function(result, final_state) -> new_resultto transform the result before returning.
Examples
# Simple usage with default tag
comp do
x <- State.get()
_ <- State.put(x + 1)
x
end
|> State.with_handler(0)
|> Comp.run!()
#=> 0
# With explicit tag
comp do
x <- State.get(:counter)
_ <- State.put(:counter, x + 1)
x
end
|> State.with_handler(0, tag: :counter)
|> Comp.run!()
#=> 0
# Include final state in result
comp do
_ <- State.modify(&(&1 + 1))
:done
end
|> State.with_handler(5, output: fn result, state -> {result, state} end)
|> Comp.run!()
#=> {:done, 6}
# Multiple states
comp do
a <- State.get(:a)
b <- State.get(:b)
{a, b}
end
|> State.with_handler(1, tag: :a)
|> State.with_handler(2, tag: :b)
|> Comp.run!()
#=> {1, 2}