Skip to content

Commit

Permalink
feat: Extend API for 'do_maybe' (#23)
Browse files Browse the repository at this point in the history
  • Loading branch information
moritzploss authored Jun 13, 2021
1 parent a68349c commit ea0abe9
Show file tree
Hide file tree
Showing 5 changed files with 166 additions and 12 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ implementations for commonly used class instances.
To install the latest version of `do` from [`hex`](https://hex.pm/packages/do),
add `do` to the `deps` in your rebar config file:

{do, "1.7.1"}
{do, "1.8.0"}

### What's in the box

Expand Down
63 changes: 63 additions & 0 deletions doc/do_maybe.html
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,21 @@ <h3 class="typedecl"><a name="type-traversable">traversable()</a></h3>

<h2><a name="index">Function Index</a></h2>
<table width="100%" border="1" cellspacing="0" cellpadding="2" summary="function index"><tr><td valign="top"><a href="#bind-2">bind/2</a></td><td></td></tr>
<tr><td valign="top"><a href="#cat_maybes-1">cat_maybes/1</a></td><td></td></tr>
<tr><td valign="top"><a href="#do-2">do/2</a></td><td></td></tr>
<tr><td valign="top"><a href="#fmap-2">fmap/2</a></td><td></td></tr>
<tr><td valign="top"><a href="#from_just-1">from_just/1</a></td><td></td></tr>
<tr><td valign="top"><a href="#from_maybe-2">from_maybe/2</a></td><td></td></tr>
<tr><td valign="top"><a href="#is_just-1">is_just/1</a></td><td></td></tr>
<tr><td valign="top"><a href="#is_nothing-1">is_nothing/1</a></td><td></td></tr>
<tr><td valign="top"><a href="#lift-1">lift/1</a></td><td></td></tr>
<tr><td valign="top"><a href="#liftA2-2">liftA2/2</a></td><td></td></tr>
<tr><td valign="top"><a href="#liftm-2">liftm/2</a></td><td></td></tr>
<tr><td valign="top"><a href="#liftmz-2">liftmz/2</a></td><td></td></tr>
<tr><td valign="top"><a href="#list_to_maybe-1">list_to_maybe/1</a></td><td></td></tr>
<tr><td valign="top"><a href="#map_maybes-2">map_maybes/2</a></td><td></td></tr>
<tr><td valign="top"><a href="#maybe-3">maybe/3</a></td><td></td></tr>
<tr><td valign="top"><a href="#maybe_to_list-1">maybe_to_list/1</a></td><td></td></tr>
<tr><td valign="top"><a href="#pure-1">pure/1</a></td><td></td></tr>
<tr><td valign="top"><a href="#sequence-1">sequence/1</a></td><td></td></tr>
<tr><td valign="top"><a href="#then-2">then/2</a></td><td></td></tr>
Expand All @@ -66,6 +75,12 @@ <h3 class="function"><a name="bind-2">bind/2</a></h3>
<p> </p>
</div>

<h3 class="function"><a name="cat_maybes-1">cat_maybes/1</a></h3>
<div class="spec">
<p><tt>cat_maybes(Maybes::[<a href="#type-maybe">maybe</a>(A)]) -&gt; [A]</tt><br></p>
<p> </p>
</div>

<h3 class="function"><a name="do-2">do/2</a></h3>
<div class="spec">
<p><tt>do(Maybe::<a href="#type-maybe">maybe</a>(A), Fs::[<a href="#type-fn">fn</a>(A, <a href="#type-maybe">maybe</a>(B)) | <a href="#type-fn">fn</a>(<a href="#type-maybe">maybe</a>(B))]) -&gt; <a href="#type-maybe">maybe</a>(B)</tt><br></p>
Expand All @@ -78,6 +93,30 @@ <h3 class="function"><a name="fmap-2">fmap/2</a></h3>
<p> </p>
</div>

<h3 class="function"><a name="from_just-1">from_just/1</a></h3>
<div class="spec">
<p><tt>from_just(X1::<a href="#type-maybe">maybe</a>(A)) -&gt; A</tt><br></p>
<p> </p>
</div>

<h3 class="function"><a name="from_maybe-2">from_maybe/2</a></h3>
<div class="spec">
<p><tt>from_maybe(A, X2::<a href="#type-maybe">maybe</a>(A)) -&gt; A</tt><br></p>
<p> </p>
</div>

<h3 class="function"><a name="is_just-1">is_just/1</a></h3>
<div class="spec">
<p><tt>is_just(X1::<a href="#type-maybe">maybe</a>(term())) -&gt; boolean()</tt><br></p>
<p> </p>
</div>

<h3 class="function"><a name="is_nothing-1">is_nothing/1</a></h3>
<div class="spec">
<p><tt>is_nothing(A::<a href="#type-maybe">maybe</a>(term())) -&gt; boolean()</tt><br></p>
<p> </p>
</div>

<h3 class="function"><a name="lift-1">lift/1</a></h3>
<div class="spec">
<p><tt>lift(F::<a href="#type-fn">fn</a>(A, B)) -&gt; <a href="#type-fn">fn</a>(<a href="#type-monad">monad</a>(A), <a href="#type-monad">monad</a>(B))</tt><br></p>
Expand All @@ -102,6 +141,30 @@ <h3 class="function"><a name="liftmz-2">liftmz/2</a></h3>
<p> </p>
</div>

<h3 class="function"><a name="list_to_maybe-1">list_to_maybe/1</a></h3>
<div class="spec">
<p><tt>list_to_maybe(X1::[A]) -&gt; <a href="#type-maybe">maybe</a>(A)</tt><br></p>
<p> </p>
</div>

<h3 class="function"><a name="map_maybes-2">map_maybes/2</a></h3>
<div class="spec">
<p><tt>map_maybes(F::<a href="#type-fn">fn</a>(A, <a href="#type-maybe">maybe</a>(B)), List::[A]) -&gt; [B]</tt><br></p>
<p> </p>
</div>

<h3 class="function"><a name="maybe-3">maybe/3</a></h3>
<div class="spec">
<p><tt>maybe(B, F::<a href="#type-fn">fn</a>(A, B), X3::<a href="#type-maybe">maybe</a>(A)) -&gt; B</tt><br></p>
<p> </p>
</div>

<h3 class="function"><a name="maybe_to_list-1">maybe_to_list/1</a></h3>
<div class="spec">
<p><tt>maybe_to_list(X1::<a href="#type-maybe">maybe</a>(A)) -&gt; [A]</tt><br></p>
<p> </p>
</div>

<h3 class="function"><a name="pure-1">pure/1</a></h3>
<div class="spec">
<p><tt>pure(A) -&gt; <a href="#type-maybe">maybe</a>(A)</tt><br></p>
Expand Down
2 changes: 1 addition & 1 deletion src/do.app.src
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{application, do,
[{description, "Monads, Functors and Do-Notation for Erlang"},
{vsn, "1.7.1"},
{vsn, "1.8.0"},
{registered, []},
{applications,
[kernel,
Expand Down
7 changes: 3 additions & 4 deletions src/do.erl
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,9 @@
-include("do.hrl").

%%%_* Macros ==================================================================
-define(MONADS, [do_either, do_list, do_maybe]).
-define(TRACE, element(2, process_info(self(), current_stacktrace))).
-define(FMAP, {_, _, 2, _}).
-define(DO, {do_monad, do, 3, _}).
-define(TRACE, element(2, process_info(self(), current_stacktrace))).
-define(FMAP, {_, _, 2, _}).
-define(DO, {do_monad, do, 3, _}).

%%%_* Code ====================================================================
%%%_* API ---------------------------------------------------------------------
Expand Down
104 changes: 98 additions & 6 deletions src/do_maybe.erl
Original file line number Diff line number Diff line change
Expand Up @@ -11,16 +11,30 @@
-behaviour(do_monad).

%%%_* Exports =================================================================
-define(API, [ bind/2,
do/2,
-define(API, [ % functor
fmap/2,
lift/1,
% applicative
liftA2/2,
liftm/2,
liftmz/2,
pure/1,
sequence/1,
then/2]).
% monad
bind/2,
do/2,
lift/1,
liftm/2,
then/2,
% maybe
cat_maybes/1,
from_just/1,
from_maybe/2,
is_just/1,
is_nothing/1,
list_to_maybe/1,
liftmz/2,
map_maybes/2,
maybe/3,
maybe_to_list/1]).

-export(?API).
-ignore_xref(?API).

Expand Down Expand Up @@ -65,6 +79,42 @@ liftmz(F, Maybes) -> do_monad:liftmz(F, Maybes, ?MODULE).
-spec then(maybe(_), fn(maybe(A))) -> maybe(A).
then(Maybe, F) -> do_monad:then(Maybe, F, ?MODULE).

%%%_* maybe -------------------------------------------------------------------
-spec maybe(B, fn(A, B), maybe(A)) -> B.
maybe(B, F, nothing) when ?isF1(F) -> B;
maybe(_, F, {just, A}) when ?isF1(F) -> F(A).

-spec is_just(maybe(_)) -> boolean().
is_just({just, _}) -> true;
is_just(nothing) -> false.

-spec is_nothing(maybe(_)) -> boolean().
is_nothing(A) -> not is_just(A).

-spec from_just(maybe(A)) -> A.
from_just({just, A}) -> A.

-spec from_maybe(A, maybe(A)) -> A.
from_maybe(A, nothing) -> A;
from_maybe(_, {just, V}) -> V.

-spec list_to_maybe([A]) -> maybe(A).
list_to_maybe([A | _]) -> pure(A);
list_to_maybe([]) -> nothing.

-spec maybe_to_list(maybe(A)) -> [A].
maybe_to_list({just, A}) -> [A];
maybe_to_list(nothing) -> [].

-spec cat_maybes([maybe(A)]) -> [A].
cat_maybes(Maybes) when is_list(Maybes) ->
lists:flatmap(fun({just, A}) -> [A];
(nothing) -> [] end, Maybes).

-spec map_maybes(fn(A, maybe(B)), [A]) -> [B].
map_maybes(F, List) when ?isF1(F), is_list(List) ->
cat_maybes(do_list:fmap(F, List)).

%%%_* internal ----------------------------------------------------------------
flat({just, nothing}) -> nothing;
flat(nothing) -> nothing;
Expand Down Expand Up @@ -124,4 +174,46 @@ do_test() ->
?assertEqual({just, 6}, do({just, 3}, [Fun0, Fun])),
?assertEqual(nothing, do(nothing, [Fun])).

maybe_test() ->
F = fun(A) -> A + 1 end,
?assertEqual(1, maybe(1, F, nothing)),
?assertEqual(2, maybe(1, F, {just, 1})).

is_just_test() ->
?assertEqual(false, is_just(nothing)),
?assertEqual(true, is_just({just, 1})).

is_nothing_test() ->
?assertEqual(true, is_nothing(nothing)),
?assertEqual(false, is_nothing({just, 1})).

from_just_test() ->
?assertEqual(1, from_just({just, 1})),
?assertError(function_clause, from_just(nothing)).

from_maybe_test() ->
?assertEqual(2, from_maybe(1, {just, 2})),
?assertEqual(1, from_maybe(1, nothing)).

list_to_maybe_test() ->
?assertEqual({just, 1}, list_to_maybe([1])),
?assertEqual({just, 1}, list_to_maybe([1, 2])),
?assertEqual(nothing, list_to_maybe([])).

maybe_to_list_test() ->
?assertEqual([1], maybe_to_list({just, 1})),
?assertEqual([], maybe_to_list(nothing)).

cat_maybes_test() ->
?assertEqual([1], cat_maybes([{just, 1}])),
?assertEqual([], cat_maybes([nothing])),
?assertEqual([], cat_maybes([])),
?assertEqual([1, 2], cat_maybes([{just, 1}, nothing, {just, 2}])).

map_maybes_test() ->
F = fun(N) when N < 5 -> {just, N};
(_) -> nothing end,
?assertEqual([], map_maybes(F, [])),
?assertEqual([1, 2, 3, 4], map_maybes(F, [1, 2, 3, 4, 5, 6, 7])).

-endif.

0 comments on commit ea0abe9

Please sign in to comment.