import gleam/erlang/process.{type Subject} type Msg(state) { Assign(state) Update(Subject(state), fn(state) -> state) Retrieve(Subject(state)) } pub opaque type State(state) { Handle(Subject(Msg(state))) } fn run(state: state, pipe: Subject(Msg(state))) -> Nil { case process.receive_forever(pipe) { _ -> run(state, pipe) } } pub fn new(initial_state: state) -> State(state) { let back_channel: Subject(Subject(Msg(state))) = process.new_subject() process.spawn(fn() { let pipe: Subject(Msg(state)) = process.new_subject() process.send(back_channel, pipe) run(initial_state, pipe) }) let pipe = process.receive_forever(back_channel) Handle(pipe) }