State, Reader & Writer

View Source

< Performance | Index | Throw & Bracket >

The three foundational effects for managing context within a computation.

State

Mutable state scoped to a computation. Operations:

x <- State.get()           # read current value
_ <- State.put(val)        # replace state
_ <- State.modify(fn x -> x + 1 end)  # update via function
x <- State.gets(fn s -> s.count end)  # read with accessor

Tagged variants for multiple independent states:

x <- State.get(:counter)   # read tagged state
_ <- State.put(:counter, 0)

Handler installation:

computation |> State.with_handler(initial_value)
computation |> State.with_handler(0, tag: :counter)

The output option transforms the result before returning:

computation |> State.with_handler(0, output: fn result, final_state ->
  {result, final_state}  # include final state in result
end)

Reader

Read-only configuration, scoped to a computation:

config <- Reader.ask()           # read current value
val <- Reader.asks(fn c -> c.key end)  # read with accessor

Scoped overrides within a computation:

Reader.local(fn config -> Map.put(config, :timeout, 5000) end, inner_comp)

Handler installation:

computation |> Reader.with_handler(%{timeout: 5000, env: :prod})

Writer

Append-only log, collected in order:

_ <- Writer.tell(%SomeEvent{})      # append an event
_ <- Writer.tell(:audit, %LogEntry{})  # tagged writer

Reading and scoping:

log <- Writer.peek()               # read current log
Writer.listen(inner_comp)          # isolate inner writer
Writer.pass(inner_comp)            # isolate, then merge into outer
Writer.censor(inner_comp, &Enum.filter(&1, fn e -> ... end))  # isolate with filter

Handler installation:

computation |> Writer.with_handler([])
computation |> Writer.with_handler([], tag: :audit)
computation |> Writer.with_handler([], output: fn result, log ->
  {result, Enum.reverse(log)}  # log in chronological order
end)

State & Environment overview

EffectReadWriteTransformTaggedHandler
Stateget/0,1, gets/1,2put/1,2modify/1,2Yeswith_handler(comp, initial, opts)
Readerask/0,1, asks/1,2local/2,3Yeswith_handler(comp, value, opts)
Writerpeek/0,1tell/1,2listen/1,2, pass/1,2, censor/2,3Yeswith_handler(comp, initial, opts)

All three support the output option for transforming the final result with handler state, and suspend for decorating ExternalSuspend data when the computation yields.


< Performance | Index | Throw & Bracket >