-module(non_empty_list). -compile([no_auto_import, nowarn_unused_vars]). -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, list_was_empty/0]). -type non_empty_list(EYW) :: {non_empty_list, EYW, list(EYW)}. -type list_was_empty() :: list_was_empty. -spec first(non_empty_list(EZI)) -> EZI. first(List) -> erlang:element(2, List). -spec do_index_map( list(FAL), list(FAN), integer(), fun((integer(), FAL) -> FAN) ) -> list(FAN). do_index_map(List, Accumulator, Index, Fun) -> case List of [] -> gleam@list:reverse(Accumulator); [First | Rest] -> do_index_map( Rest, [Fun(Index, First) | Accumulator], Index + 1, Fun ) end. -spec last(non_empty_list(FAT)) -> FAT. last(List) -> _pipe = gleam@list:last(erlang:element(3, List)), gleam@result:unwrap(_pipe, erlang:element(2, List)). -spec new(FBR, list(FBR)) -> non_empty_list(FBR). new(First, Rest) -> {non_empty_list, First, Rest}. -spec append_list(non_empty_list(EZB), list(EZB)) -> non_empty_list(EZB). append_list(First, Second) -> new( erlang:element(2, First), gleam@list:append(erlang:element(3, First), Second) ). -spec from_list(list(FAC)) -> {ok, non_empty_list(FAC)} | {error, list_was_empty()}. from_list(List) -> case List of [] -> {error, list_was_empty}; [First | Rest] -> {ok, new(First, Rest)} end. -spec index_map(non_empty_list(FAH), fun((integer(), FAH) -> FAJ)) -> non_empty_list(FAJ). 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(FAQ), FAQ) -> non_empty_list(FAQ). intersperse(List, Elem) -> new( erlang:element(2, List), [Elem | gleam@list:intersperse(erlang:element(3, List), Elem)] ). -spec map(non_empty_list(FAV), fun((FAV) -> FAX)) -> non_empty_list(FAX). map(List, Fun) -> new( Fun(erlang:element(2, List)), gleam@list:map(erlang:element(3, List), Fun) ). -spec prepend(non_empty_list(FBU), FBU) -> non_empty_list(FBU). prepend(List, Item) -> new(Item, [erlang:element(2, List) | erlang:element(3, List)]). -spec reduce(non_empty_list(FBX), fun((FBX, FBX) -> FBX)) -> FBX. reduce(List, Fun) -> gleam@list:fold(erlang:element(3, List), erlang:element(2, List), Fun). -spec rest(non_empty_list(FBZ)) -> list(FBZ). rest(List) -> erlang:element(3, List). -spec single(FCM) -> non_empty_list(FCM). single(First) -> new(First, []). -spec to_list(non_empty_list(FDB)) -> list(FDB). to_list(Non_empty) -> [erlang:element(2, Non_empty) | erlang:element(3, Non_empty)]. -spec append(non_empty_list(EYX), non_empty_list(EYX)) -> non_empty_list(EYX). append(First, Second) -> new( erlang:element(2, First), gleam@list:append(erlang:element(3, First), to_list(Second)) ). -spec drop(non_empty_list(EZF), integer()) -> list(EZF). drop(List, N) -> _pipe = List, _pipe@1 = to_list(_pipe), gleam@list:drop(_pipe@1, N). -spec reverse_and_prepend(non_empty_list(EZY), non_empty_list(EZY)) -> non_empty_list(EZY). 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(FCC)) -> non_empty_list(FCC). reverse(List) -> _assert_subject = begin _pipe = List, _pipe@1 = to_list(_pipe), _pipe@2 = gleam@list: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 => 417}) end, Reversed. -spec do_flatten(list(non_empty_list(EZT)), non_empty_list(EZT)) -> non_empty_list(EZT). 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(EZP))) -> non_empty_list(EZP). flatten(Lists) -> do_flatten(erlang:element(3, Lists), reverse(erlang:element(2, Lists))). -spec flat_map(non_empty_list(EZK), fun((EZK) -> non_empty_list(EZM))) -> non_empty_list(EZM). flat_map(List, Fun) -> _pipe = List, _pipe@1 = map(_pipe, Fun), flatten(_pipe@1). -spec do_map2(non_empty_list(FBF), list(FBH), list(FBJ), fun((FBH, FBJ) -> FBF)) -> non_empty_list(FBF). 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(FAZ), non_empty_list(FBB), fun((FAZ, FBB) -> FBD)) -> non_empty_list(FBD). 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(FBM), FBO, fun((FBO, FBM) -> {FBO, FBP})) -> {FBO, non_empty_list(FBP)}. 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(FCF), FCH, fun((FCH, FCF) -> FCH)) -> non_empty_list(FCH). 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 => 439}) end, Scanned. -spec shuffle(non_empty_list(FCJ)) -> non_empty_list(FCJ). 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 => 462}) end, Shuffled. -spec sort(non_empty_list(FCO), fun((FCO, FCO) -> gleam@order:order())) -> non_empty_list(FCO). 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 => 498}) end, Sorted. -spec take(non_empty_list(FCY), integer()) -> list(FCY). take(List, N) -> _pipe = List, _pipe@1 = to_list(_pipe), gleam@list:take(_pipe@1, N). -spec unique(non_empty_list(FDE)) -> non_empty_list(FDE). 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 => 596}) end, Unique. -spec unzip(non_empty_list({FDH, FDI})) -> {non_empty_list(FDH), non_empty_list(FDI)}. 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(FDM), non_empty_list(FDO)) -> non_empty_list({FDM, FDO}). 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(FCR), non_empty_list(FCT)) -> {ok, non_empty_list({FCR, FCT})} | {error, gleam@list:length_mismatch()}. strict_zip(List, Other) -> case gleam@list:length(to_list(List)) =:= gleam@list:length(to_list(Other)) of true -> {ok, zip(List, Other)}; false -> {error, length_mismatch} end.