Packages

Compose stateful actions to simulate mutable state

Current section

Files

Jump to
act src act.erl
Raw

src/act.erl

-module(act).
-compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]).
-export([run/2, eval/2, exec/2, return/1, ok/1, error/1, get_state/0, set_state/1, update_state/1, map/2, map_ok/2, map_error/2, do/2, 'try'/2, all/1, each/1, try_all/1, try_each/1]).
-spec run(fun((FKC) -> {FKC, FKB}), FKC) -> {FKC, FKB}.
run(Action, State) ->
Action(State).
-spec eval(fun((FKG) -> {FKG, FKF}), FKG) -> FKF.
eval(Action, State) ->
erlang:element(2, Action(State)).
-spec exec(fun((FKK) -> {FKK, any()}), FKK) -> FKK.
exec(Action, State) ->
erlang:element(1, Action(State)).
-spec return(FKN) -> fun((FKO) -> {FKO, FKN}).
return(Result) ->
fun(State) -> {State, Result} end.
-spec ok(FKR) -> fun((FKT) -> {FKT, {ok, FKR} | {error, any()}}).
ok(Value) ->
fun(State) -> {State, {ok, Value}} end.
-spec error(FKX) -> fun((FKZ) -> {FKZ, {ok, any()} | {error, FKX}}).
error(Value) ->
fun(State) -> {State, {error, Value}} end.
-spec get_state() -> fun((FLD) -> {FLD, FLD}).
get_state() ->
fun(State) -> {State, State} end.
-spec set_state(FLG) -> fun((FLG) -> {FLG, nil}).
set_state(State) ->
fun(_) -> {State, nil} end.
-spec update_state(fun((FLJ) -> FLJ)) -> fun((FLJ) -> {FLJ, nil}).
update_state(Updater) ->
fun(State) -> {Updater(State), nil} end.
-spec map(fun((FLN) -> {FLN, FLM}), fun((FLM) -> FLQ)) -> fun((FLN) -> {FLN,
FLQ}).
map(Action, F) ->
fun(State) ->
{State@1, Result} = Action(State),
{State@1, F(Result)}
end.
-spec map_ok(fun((FLV) -> {FLV, {ok, FLT} | {error, FLU}}), fun((FLT) -> FLZ)) -> fun((FLV) -> {FLV,
{ok, FLZ} | {error, FLU}}).
map_ok(Action, F) ->
fun(State) ->
{State@1, Result} = Action(State),
case Result of
{ok, A} ->
{State@1, {ok, F(A)}};
{error, E} ->
{State@1, {error, E}}
end
end.
-spec map_error(
fun((FMF) -> {FMF, {ok, FMD} | {error, FME}}),
fun((FME) -> FMJ)
) -> fun((FMF) -> {FMF, {ok, FMD} | {error, FMJ}}).
map_error(Action, F) ->
fun(State) ->
{State@1, Result} = Action(State),
case Result of
{error, E} ->
{State@1, {error, F(E)}};
{ok, A} ->
{State@1, {ok, A}}
end
end.
-spec do(fun((FMO) -> {FMO, FMN}), fun((FMN) -> fun((FMO) -> {FMO, FMR}))) -> fun((FMO) -> {FMO,
FMR}).
do(First_do, And_then) ->
fun(State) ->
{State@1, Result} = First_do(State),
(And_then(Result))(State@1)
end.
-spec 'try'(
fun((FMY) -> {FMY, {ok, FMW} | {error, FMX}}),
fun((FMW) -> fun((FMY) -> {FMY, {ok, FNC} | {error, FMX}}))
) -> fun((FMY) -> {FMY, {ok, FNC} | {error, FMX}}).
'try'(First_try, And_then) ->
fun(State) ->
{State@1, Result} = First_try(State),
case Result of
{ok, A} ->
(And_then(A))(State@1);
{error, E} ->
{State@1, {error, E}}
end
end.
-spec all(list(fun((FNK) -> {FNK, FNJ}))) -> fun((FNK) -> {FNK, list(FNJ)}).
all(Actions) ->
fun(_capture) ->
gleam@list:map_fold(
Actions,
_capture,
fun(State, Action) -> Action(State) end
)
end.
-spec each(list(fun((FNS) -> {FNS, any()}))) -> fun((FNS) -> {FNS, nil}).
each(Actions) ->
fun(State) ->
{gleam@list:fold(
Actions,
State,
fun(State@1, Action) -> erlang:element(1, Action(State@1)) end
),
nil}
end.
-spec try_all(list(fun((FOA) -> {FOA, {ok, FNY} | {error, FNZ}}))) -> fun((FOA) -> {FOA,
{ok, list(FNY)} | {error, FNZ}}).
try_all(Actions) ->
_pipe = fun(State) ->
gleam@list:fold_until(
Actions,
{State, {ok, []}},
fun(Acc, Action) ->
{State@1, {ok, Results}} = case Acc of
{_, {ok, _}} -> Acc;
_assert_fail ->
erlang:error(#{gleam_error => let_assert,
message => <<"Assertion pattern match failed"/utf8>>,
value => _assert_fail,
module => <<"act"/utf8>>,
function => <<"try_all"/utf8>>,
line => 283})
end,
case Action(State@1) of
{New_state, {ok, Result}} ->
{continue, {New_state, {ok, [Result | Results]}}};
{New_state@1, {error, Result@1}} ->
{stop, {New_state@1, {error, Result@1}}}
end
end
)
end,
map_ok(_pipe, fun gleam@list:reverse/1).
-spec try_each(list(fun((FOL) -> {FOL, {ok, any()} | {error, FOK}}))) -> fun((FOL) -> {FOL,
{ok, nil} | {error, FOK}}).
try_each(Actions) ->
fun(State) ->
gleam@list:fold_until(
Actions,
{State, {ok, nil}},
fun(Acc, Action) ->
{State@1, Nil_result} = Acc,
case Action(State@1) of
{New_state, {ok, _}} ->
{continue, {New_state, Nil_result}};
{New_state@1, {error, Result}} ->
{stop, {New_state@1, {error, Result}}}
end
end
)
end.