-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, list_was_empty/0]). -type non_empty_list(FOF) :: {non_empty_list, FOF, list(FOF)}. -type list_was_empty() :: list_was_empty. -spec first(non_empty_list(FOR)) -> FOR. first(List) -> erlang:element(2, List). -spec do_index_map( list(FPU), list(FPW), integer(), fun((integer(), FPU) -> FPW) ) -> list(FPW). 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(FQC)) -> FQC. last(List) -> _pipe = gleam@list:last(erlang:element(3, List)), gleam@result:unwrap(_pipe, erlang:element(2, List)). -spec new(FRA, list(FRA)) -> non_empty_list(FRA). new(First, Rest) -> {non_empty_list, First, Rest}. -spec append_list(non_empty_list(FOK), list(FOK)) -> non_empty_list(FOK). append_list(First, Second) -> new( erlang:element(2, First), gleam@list:append(erlang:element(3, First), Second) ). -spec from_list(list(FPL)) -> {ok, non_empty_list(FPL)} | {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(FPQ), fun((integer(), FPQ) -> FPS)) -> non_empty_list(FPS). 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(FPZ), FPZ) -> non_empty_list(FPZ). intersperse(List, Elem) -> new( erlang:element(2, List), [Elem | gleam@list:intersperse(erlang:element(3, List), Elem)] ). -spec map(non_empty_list(FQE), fun((FQE) -> FQG)) -> non_empty_list(FQG). map(List, Fun) -> new( Fun(erlang:element(2, List)), gleam@list:map(erlang:element(3, List), Fun) ). -spec prepend(non_empty_list(FRD), FRD) -> non_empty_list(FRD). prepend(List, Item) -> new(Item, [erlang:element(2, List) | erlang:element(3, List)]). -spec reduce(non_empty_list(FRG), fun((FRG, FRG) -> FRG)) -> FRG. reduce(List, Fun) -> gleam@list:fold(erlang:element(3, List), erlang:element(2, List), Fun). -spec rest(non_empty_list(FRI)) -> list(FRI). rest(List) -> erlang:element(3, List). -spec single(FRV) -> non_empty_list(FRV). single(First) -> new(First, []). -spec to_list(non_empty_list(FSK)) -> list(FSK). to_list(Non_empty) -> [erlang:element(2, Non_empty) | erlang:element(3, Non_empty)]. -spec append(non_empty_list(FOG), non_empty_list(FOG)) -> non_empty_list(FOG). append(First, Second) -> new( erlang:element(2, First), gleam@list:append(erlang:element(3, First), to_list(Second)) ). -spec drop(non_empty_list(FOO), integer()) -> list(FOO). drop(List, N) -> _pipe = List, _pipe@1 = to_list(_pipe), gleam@list:drop(_pipe@1, N). -spec reverse_and_prepend(non_empty_list(FPH), non_empty_list(FPH)) -> non_empty_list(FPH). 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(FRL)) -> non_empty_list(FRL). 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 => 416}) end, Reversed. -spec do_flatten(list(non_empty_list(FPC)), non_empty_list(FPC)) -> non_empty_list(FPC). 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(FOY))) -> non_empty_list(FOY). flatten(Lists) -> do_flatten(erlang:element(3, Lists), reverse(erlang:element(2, Lists))). -spec flat_map(non_empty_list(FOT), fun((FOT) -> non_empty_list(FOV))) -> non_empty_list(FOV). flat_map(List, Fun) -> _pipe = List, _pipe@1 = map(_pipe, Fun), flatten(_pipe@1). -spec do_map2(non_empty_list(FQO), list(FQQ), list(FQS), fun((FQQ, FQS) -> FQO)) -> non_empty_list(FQO). 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(FQI), non_empty_list(FQK), fun((FQI, FQK) -> FQM)) -> non_empty_list(FQM). 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(FQV), FQX, fun((FQX, FQV) -> {FQX, FQY})) -> {FQX, non_empty_list(FQY)}. 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(FRO), FRQ, fun((FRQ, FRO) -> FRQ)) -> non_empty_list(FRQ). 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 => 438}) end, Scanned. -spec shuffle(non_empty_list(FRS)) -> non_empty_list(FRS). 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 => 461}) end, Shuffled. -spec sort(non_empty_list(FRX), fun((FRX, FRX) -> gleam@order:order())) -> non_empty_list(FRX). 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 => 497}) end, Sorted. -spec take(non_empty_list(FSH), integer()) -> list(FSH). take(List, N) -> _pipe = List, _pipe@1 = to_list(_pipe), gleam@list:take(_pipe@1, N). -spec unique(non_empty_list(FSN)) -> non_empty_list(FSN). 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 => 595}) end, Unique. -spec unzip(non_empty_list({FSQ, FSR})) -> {non_empty_list(FSQ), non_empty_list(FSR)}. 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(FSV), non_empty_list(FSX)) -> non_empty_list({FSV, FSX}). 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(FSA), non_empty_list(FSC)) -> {ok, non_empty_list({FSA, FSC})} | {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.