Current section
Files
Jump to
Current section
Files
src/do_traversable.erl
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%% @doc
%%% @end
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%_* Module declaration ======================================================
-module(do_traversable).
%%%_* Includes ================================================================
-include("do_macros.hrl").
-include("do_types.hrl").
%%%_* Exports =================================================================
-define(API, [ sequence/2,
traverse/2]).
-export(?API).
-ignore_xref(?API).
%%%_* Code ====================================================================
%%%_* API ---------------------------------------------------------------------
-spec sequence(traversable(applicative(A)), atom()) -> applicative(traversable(A)).
sequence([F | Rest], Mod) when ?isF0(F) ->
sequence([F() | Rest], Mod);
sequence([Elm | Rest], Mod) ->
Mod:liftA2(fun(Val, Vals) -> [Val | Vals] end, Elm, sequence(Rest, Mod));
sequence([], Mod) ->
Mod:pure([]);
sequence(Map, Mod) when is_map(Map) ->
{Keys, Vals} = lists:unzip(maps:to_list(Map)),
Mod:fmap(fun(Sequenced) -> maps:from_list(lists:zip(Keys, Sequenced)) end,
sequence(Vals, Mod)).
-spec traverse(fn(A, applicative(B)), traversable(A)) -> applicative(traversable(B)).
traverse(F, Traversable) when ?isF1(F) -> do_functor:fmap(F, Traversable).
%%%_* Tests ===================================================================
-ifdef(TEST).
-include_lib("eunit/include/eunit.hrl").
traverse_test() ->
F = fun(A) -> A + 1 end,
?assertEqual([1, 2, 3], traverse(F, [0, 1, 2])),
?assertEqual(#{a => 1, b => 2, c => 3}, traverse(F, #{a => 0, b => 1, c => 2})).
-endif.