-module(non_empty_list). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([first/1, last/1, new/2, append_list/2, from_list/1, index_map/2, intersperse/2, map/2, prepend/2, reduce/2, rest/1, single/1, to_list/1, append/2, drop/2, reverse/1, flatten/1, flat_map/2, map2/3, map_fold/3, scan/3, shuffle/1, sort/2, take/2, unique/1, unzip/1, zip/2, strict_zip/2]). -export_type([non_empty_list/1]). -type non_empty_list(FLP) :: {non_empty_list, FLP, list(FLP)}. -spec first(non_empty_list(FMB)) -> FMB. first(List) -> erlang:element(2, List). -spec do_index_map( list(FNE), list(FNG), integer(), fun((integer(), FNE) -> FNG) ) -> list(FNG). do_index_map(List, Accumulator, Index, Fun) -> case List of [] -> lists:reverse(Accumulator); [First | Rest] -> do_index_map( Rest, [Fun(Index, First) | Accumulator], Index + 1, Fun ) end. -spec last(non_empty_list(FNM)) -> FNM. last(List) -> _pipe = gleam@list:last(erlang:element(3, List)), gleam@result:unwrap(_pipe, erlang:element(2, List)). -spec new(FOK, list(FOK)) -> non_empty_list(FOK). new(First, Rest) -> {non_empty_list, First, Rest}. -spec append_list(non_empty_list(FLU), list(FLU)) -> non_empty_list(FLU). append_list(First, Second) -> new( erlang:element(2, First), lists:append(erlang:element(3, First), Second) ). -spec from_list(list(FMV)) -> {ok, non_empty_list(FMV)} | {error, nil}. from_list(List) -> case List of [] -> {error, nil}; [First | Rest] -> {ok, new(First, Rest)} end. -spec index_map(non_empty_list(FNA), fun((integer(), FNA) -> FNC)) -> non_empty_list(FNC). index_map(List, Fun) -> new( Fun(0, erlang:element(2, List)), do_index_map(erlang:element(3, List), [], 1, Fun) ). -spec intersperse(non_empty_list(FNJ), FNJ) -> non_empty_list(FNJ). intersperse(List, Elem) -> new( erlang:element(2, List), [Elem | gleam@list:intersperse(erlang:element(3, List), Elem)] ). -spec map(non_empty_list(FNO), fun((FNO) -> FNQ)) -> non_empty_list(FNQ). map(List, Fun) -> new( Fun(erlang:element(2, List)), gleam@list:map(erlang:element(3, List), Fun) ). -spec prepend(non_empty_list(FON), FON) -> non_empty_list(FON). prepend(List, Item) -> new(Item, [erlang:element(2, List) | erlang:element(3, List)]). -spec reduce(non_empty_list(FOQ), fun((FOQ, FOQ) -> FOQ)) -> FOQ. reduce(List, Fun) -> gleam@list:fold(erlang:element(3, List), erlang:element(2, List), Fun). -spec rest(non_empty_list(FOS)) -> list(FOS). rest(List) -> erlang:element(3, List). -spec single(FPF) -> non_empty_list(FPF). single(First) -> new(First, []). -spec to_list(non_empty_list(FPU)) -> list(FPU). to_list(Non_empty) -> [erlang:element(2, Non_empty) | erlang:element(3, Non_empty)]. -spec append(non_empty_list(FLQ), non_empty_list(FLQ)) -> non_empty_list(FLQ). append(First, Second) -> new( erlang:element(2, First), lists:append(erlang:element(3, First), to_list(Second)) ). -spec drop(non_empty_list(FLY), integer()) -> list(FLY). drop(List, N) -> _pipe = List, _pipe@1 = to_list(_pipe), gleam@list:drop(_pipe@1, N). -spec reverse_and_prepend(non_empty_list(FMR), non_empty_list(FMR)) -> non_empty_list(FMR). reverse_and_prepend(Prefix, Suffix) -> case erlang:element(3, Prefix) of [] -> new(erlang:element(2, Prefix), to_list(Suffix)); [First | Rest] -> reverse_and_prepend( new(First, Rest), new(erlang:element(2, Prefix), to_list(Suffix)) ) end. -spec reverse(non_empty_list(FOV)) -> non_empty_list(FOV). reverse(List) -> _assert_subject = begin _pipe = List, _pipe@1 = to_list(_pipe), _pipe@2 = lists:reverse(_pipe@1), from_list(_pipe@2) end, {ok, Reversed} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"non_empty_list"/utf8>>, function => <<"reverse"/utf8>>, line => 427}) end, Reversed. -spec do_flatten(list(non_empty_list(FMM)), non_empty_list(FMM)) -> non_empty_list(FMM). do_flatten(Lists, Accumulator) -> case Lists of [] -> reverse(Accumulator); [List | Further_lists] -> do_flatten(Further_lists, reverse_and_prepend(List, Accumulator)) end. -spec flatten(non_empty_list(non_empty_list(FMI))) -> non_empty_list(FMI). flatten(Lists) -> do_flatten(erlang:element(3, Lists), reverse(erlang:element(2, Lists))). -spec flat_map(non_empty_list(FMD), fun((FMD) -> non_empty_list(FMF))) -> non_empty_list(FMF). flat_map(List, Fun) -> _pipe = List, _pipe@1 = map(_pipe, Fun), flatten(_pipe@1). -spec do_map2(non_empty_list(FNY), list(FOA), list(FOC), fun((FOA, FOC) -> FNY)) -> non_empty_list(FNY). do_map2(Acc, List1, List2, Fun) -> case {List1, List2} of {[], _} -> reverse(Acc); {_, []} -> reverse(Acc); {[First_a | Rest_as], [First_b | Rest_bs]} -> _pipe = prepend(Acc, Fun(First_a, First_b)), do_map2(_pipe, Rest_as, Rest_bs, Fun) end. -spec map2(non_empty_list(FNS), non_empty_list(FNU), fun((FNS, FNU) -> FNW)) -> non_empty_list(FNW). map2(List1, List2, Fun) -> do_map2( single(Fun(erlang:element(2, List1), erlang:element(2, List2))), erlang:element(3, List1), erlang:element(3, List2), Fun ). -spec map_fold(non_empty_list(FOF), FOH, fun((FOH, FOF) -> {FOH, FOI})) -> {FOH, non_empty_list(FOI)}. map_fold(List, Acc, Fun) -> {Acc@1, First_elem} = Fun(Acc, erlang:element(2, List)), _pipe = gleam@list:fold( erlang:element(3, List), {Acc@1, single(First_elem)}, fun(Acc_non_empty, Item) -> {Acc@2, Non_empty} = Acc_non_empty, {Acc@3, New_item} = Fun(Acc@2, Item), {Acc@3, prepend(Non_empty, New_item)} end ), gleam@pair:map_second(_pipe, fun reverse/1). -spec scan(non_empty_list(FOY), FPA, fun((FPA, FOY) -> FPA)) -> non_empty_list(FPA). scan(List, Initial, Fun) -> _assert_subject = begin _pipe = List, _pipe@1 = to_list(_pipe), _pipe@2 = gleam@list:scan(_pipe@1, Initial, Fun), from_list(_pipe@2) end, {ok, Scanned} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"non_empty_list"/utf8>>, function => <<"scan"/utf8>>, line => 450}) end, Scanned. -spec shuffle(non_empty_list(FPC)) -> non_empty_list(FPC). shuffle(List) -> _assert_subject = begin _pipe = List, _pipe@1 = to_list(_pipe), _pipe@2 = gleam@list:shuffle(_pipe@1), from_list(_pipe@2) end, {ok, Shuffled} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"non_empty_list"/utf8>>, function => <<"shuffle"/utf8>>, line => 473}) end, Shuffled. -spec sort(non_empty_list(FPH), fun((FPH, FPH) -> gleam@order:order())) -> non_empty_list(FPH). sort(List, Compare) -> _assert_subject = begin _pipe = List, _pipe@1 = to_list(_pipe), _pipe@2 = gleam@list:sort(_pipe@1, Compare), from_list(_pipe@2) end, {ok, Sorted} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"non_empty_list"/utf8>>, function => <<"sort"/utf8>>, line => 510}) end, Sorted. -spec take(non_empty_list(FPR), integer()) -> list(FPR). take(List, N) -> _pipe = List, _pipe@1 = to_list(_pipe), gleam@list:take(_pipe@1, N). -spec unique(non_empty_list(FPX)) -> non_empty_list(FPX). unique(List) -> _assert_subject = begin _pipe = List, _pipe@1 = to_list(_pipe), _pipe@2 = gleam@list:unique(_pipe@1), from_list(_pipe@2) end, {ok, Unique} = case _assert_subject of {ok, _} -> _assert_subject; _assert_fail -> erlang:error(#{gleam_error => let_assert, message => <<"Assertion pattern match failed"/utf8>>, value => _assert_fail, module => <<"non_empty_list"/utf8>>, function => <<"unique"/utf8>>, line => 611}) end, Unique. -spec unzip(non_empty_list({FQA, FQB})) -> {non_empty_list(FQA), non_empty_list(FQB)}. unzip(List) -> _pipe = gleam@list:unzip(erlang:element(3, List)), _pipe@1 = gleam@pair:map_first( _pipe, fun(_capture) -> new(erlang:element(1, erlang:element(2, List)), _capture) end ), gleam@pair:map_second( _pipe@1, fun(_capture@1) -> new(erlang:element(2, erlang:element(2, List)), _capture@1) end ). -spec zip(non_empty_list(FQF), non_empty_list(FQH)) -> non_empty_list({FQF, FQH}). zip(List, Other) -> new( {erlang:element(2, List), erlang:element(2, Other)}, gleam@list:zip(erlang:element(3, List), erlang:element(3, Other)) ). -spec strict_zip(non_empty_list(FPK), non_empty_list(FPM)) -> {ok, non_empty_list({FPK, FPM})} | {error, nil}. strict_zip(List, Other) -> case erlang:length(to_list(List)) =:= erlang:length(to_list(Other)) of true -> {ok, zip(List, Other)}; false -> {error, nil} end.