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([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 return(FKB) -> fun((FKC) -> {FKC, FKB}).
return(Result) ->
fun(State) -> {State, Result} end.
-spec ok(FKF) -> fun((FKH) -> {FKH, {ok, FKF} | {error, any()}}).
ok(Value) ->
fun(State) -> {State, {ok, Value}} end.
-spec error(FKL) -> fun((FKN) -> {FKN, {ok, any()} | {error, FKL}}).
error(Value) ->
fun(State) -> {State, {error, Value}} end.
-spec get_state() -> fun((FKR) -> {FKR, FKR}).
get_state() ->
fun(State) -> {State, State} end.
-spec set_state(FKU) -> fun((FKU) -> {FKU, nil}).
set_state(State) ->
fun(_) -> {State, nil} end.
-spec update_state(fun((FKX) -> FKX)) -> fun((FKX) -> {FKX, nil}).
update_state(Updater) ->
fun(State) -> {Updater(State), nil} end.
-spec map(fun((FLB) -> {FLB, FLA}), fun((FLA) -> FLE)) -> fun((FLB) -> {FLB,
FLE}).
map(Action, F) ->
fun(State) ->
{State@1, Result} = Action(State),
{State@1, F(Result)}
end.
-spec map_ok(fun((FLJ) -> {FLJ, {ok, FLH} | {error, FLI}}), fun((FLH) -> FLN)) -> fun((FLJ) -> {FLJ,
{ok, FLN} | {error, FLI}}).
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((FLT) -> {FLT, {ok, FLR} | {error, FLS}}),
fun((FLS) -> FLX)
) -> fun((FLT) -> {FLT, {ok, FLR} | {error, FLX}}).
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((FMC) -> {FMC, FMB}), fun((FMB) -> fun((FMC) -> {FMC, FMF}))) -> fun((FMC) -> {FMC,
FMF}).
do(First_do, And_then) ->
fun(State) ->
{State@1, Result} = First_do(State),
(And_then(Result))(State@1)
end.
-spec 'try'(
fun((FMM) -> {FMM, {ok, FMK} | {error, FML}}),
fun((FMK) -> fun((FMM) -> {FMM, {ok, FMQ} | {error, FML}}))
) -> fun((FMM) -> {FMM, {ok, FMQ} | {error, FML}}).
'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((FMY) -> {FMY, FMX}))) -> fun((FMY) -> {FMY, list(FMX)}).
all(Actions) ->
fun(_capture) ->
gleam@list:map_fold(
Actions,
_capture,
fun(State, Action) -> Action(State) end
)
end.
-spec each(list(fun((FNG) -> {FNG, any()}))) -> fun((FNG) -> {FNG, 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((FNO) -> {FNO, {ok, FNM} | {error, FNN}}))) -> fun((FNO) -> {FNO,
{ok, list(FNM)} | {error, FNN}}).
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 => 246})
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((FNZ) -> {FNZ, {ok, any()} | {error, FNY}}))) -> fun((FNZ) -> {FNZ,
{ok, nil} | {error, FNY}}).
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.