Current section
Files
Jump to
Current section
Files
src/trie.erl
-module(trie).
-compile([no_auto_import, nowarn_unused_vars]).
-export([map/2, new/0, delete/2, fold/3, paths/1, size/1, is_empty/1, to_list/1, values/1, insert/3, from_list/1, singleton/2, get/2, has_path/2, update/3]).
-export_type([trie/2]).
-opaque trie(EWX, EWY) :: {trie,
gleam@option:option(EWY),
gleam@map:map_(EWX, trie(EWX, EWY))}.
-spec do_delete(trie(EXG, EXH), list(EXG)) -> gleam@option:option(trie(EXG, EXH)).
do_delete(Trie, Path) ->
case {Path, Trie} of
{[], {trie, _, Children_map}} ->
case gleam@map:size(Children_map) of
0 ->
none;
_ ->
{some, {trie, none, Children_map}}
end;
{[First | Rest], {trie, Entry, Children_map@1}} ->
New_children = case gleam@map:get(Children_map@1, First) of
{error, _} ->
Children_map@1;
{ok, Child} ->
case do_delete(Child, Rest) of
none ->
gleam@map:delete(Children_map@1, First);
{some, Trie@1} ->
gleam@map:insert(Children_map@1, First, Trie@1)
end
end,
case {Entry, gleam@map:size(New_children)} of
{none, 0} ->
none;
{_, _} ->
{some, {trie, Entry, New_children}}
end
end.
-spec map(trie(EYX, EYY), fun((EYY) -> EZB)) -> trie(EYX, EZB).
map(Trie, Fun) ->
{trie,
gleam@option:map(erlang:element(2, Trie), Fun),
gleam@map:map_values(
erlang:element(3, Trie),
fun(_, T) -> map(T, Fun) end
)}.
-spec new() -> trie(any(), any()).
new() ->
{trie, none, gleam@map:new()}.
-spec delete(trie(EWZ, EXA), list(EWZ)) -> trie(EWZ, EXA).
delete(Trie, Path) ->
_pipe = do_delete(Trie, Path),
gleam@option:unwrap(_pipe, new()).
-spec fold(trie(EXO, EXP), EXS, fun((EXS, list(EXO), EXP) -> EXS)) -> EXS.
fold(Trie, Initial, Fun) ->
gleam@map:fold(
erlang:element(3, Trie),
begin
_pipe = erlang:element(2, Trie),
_pipe@1 = gleam@option:map(
_pipe,
fun(_capture) -> Fun(Initial, [], _capture) end
),
gleam@option:unwrap(_pipe@1, Initial)
end,
fun(Acc, First, Trie@1) ->
fold(
Trie@1,
Acc,
fun(Acc@1, Rest, Value) -> Fun(Acc@1, [First | Rest], Value) end
)
end
).
-spec paths(trie(EZI, any())) -> list(list(EZI)).
paths(Trie) ->
fold(Trie, [], fun(Rest, Path, _) -> [Path | Rest] end).
-spec size(trie(any(), any())) -> integer().
size(Trie) ->
fold(Trie, 0, fun(Acc, _, _) -> Acc + 1 end).
-spec is_empty(trie(any(), any())) -> boolean().
is_empty(Trie) ->
size(Trie) =:= 0.
-spec to_list(trie(EZX, EZY)) -> list({list(EZX), EZY}).
to_list(Trie) ->
fold(Trie, [], fun(Rest, Path, Value) -> [{Path, Value} | Rest] end).
-spec values(trie(any(), FAX)) -> list(FAX).
values(Trie) ->
fold(Trie, [], fun(Values, _, Value) -> [Value | Values] end).
-spec insert(trie(EYM, EYN), list(EYM), EYN) -> trie(EYM, EYN).
insert(Trie, Path, Value) ->
case {Path, Trie} of
{[], {trie, _, Children_map}} ->
{trie, {some, Value}, Children_map};
{[First | Rest], {trie, Entry, Children_map@1}} ->
_pipe = gleam@map:get(Children_map@1, First),
_pipe@1 = gleam@result:unwrap(_pipe, new()),
_pipe@2 = insert(_pipe@1, Rest, Value),
_pipe@3 = gleam@map:insert(Children_map@1, First, _pipe@2),
{trie, Entry, _pipe@3}
end.
-spec from_list(list({list(EXU), EXW})) -> trie(EXU, EXW).
from_list(List) ->
gleam@list:fold(
List,
new(),
fun(Trie, Pair) ->
insert(Trie, erlang:element(1, Pair), erlang:element(2, Pair))
end
).
-spec singleton(list(EZO), EZQ) -> trie(EZO, EZQ).
singleton(Path, Value) ->
insert(new(), Path, Value).
-spec get(trie(EYA, EYB), list(EYA)) -> {ok, EYB} | {error, nil}.
get(From, Path) ->
case {Path, From} of
{[], {trie, none, _}} ->
{error, nil};
{[], {trie, {some, Value}, _}} ->
{ok, Value};
{[First | Rest], {trie, _, Children_map}} ->
_pipe = Children_map,
_pipe@1 = gleam@map:get(_pipe, First),
gleam@result:then(_pipe@1, fun(_capture) -> get(_capture, Rest) end)
end.
-spec has_path(trie(EYH, any()), list(EYH)) -> boolean().
has_path(Trie, Path) ->
case get(Trie, Path) of
{ok, _} ->
true;
{error, _} ->
false
end.
-spec do_update(
trie(FAM, FAN),
list(FAM),
fun((gleam@option:option(FAN)) -> gleam@option:option(FAN))
) -> gleam@option:option(trie(FAM, FAN)).
do_update(Trie, Path, Fun) ->
case {Path, Trie} of
{[], {trie, Entry, Children_map}} ->
case {Fun(Entry), gleam@map:size(Children_map)} of
{none, 0} ->
none;
{_ = New_entry, _} ->
{some, {trie, New_entry, Children_map}}
end;
{[First | Rest], {trie, Entry@1, Children_map@1}} ->
New_children = case gleam@map:get(Children_map@1, First) of
{ok, Child} ->
case do_update(Child, Rest, Fun) of
none ->
gleam@map:delete(Children_map@1, First);
{some, New_child} ->
gleam@map:insert(Children_map@1, First, New_child)
end;
{error, _} ->
case Fun(none) of
none ->
Children_map@1;
{some, Value} ->
gleam@map:insert(
Children_map@1,
First,
singleton(Rest, Value)
)
end
end,
case {Entry@1, gleam@map:size(New_children)} of
{none, 0} ->
none;
{_, _} ->
{some, {trie, Entry@1, New_children}}
end
end.
-spec update(
trie(FAD, FAE),
list(FAD),
fun((gleam@option:option(FAE)) -> gleam@option:option(FAE))
) -> trie(FAD, FAE).
update(Trie, Path, Fun) ->
_pipe = do_update(Trie, Path, Fun),
gleam@option:unwrap(_pipe, new()).