Skip to content

Instantly share code, notes, and snippets.

@ericmoritz
Last active December 18, 2015 05:39
Show Gist options
  • Save ericmoritz/5734333 to your computer and use it in GitHub Desktop.
Save ericmoritz/5734333 to your computer and use it in GitHub Desktop.
I think I finally understand monads!
-module(erlmonad).
-compile(export_all).
half(X) when X rem 2 =/= 0 ->
nothing;
half(X) ->
X div 2.
divide(_X, 0) ->
{error, divbyzero};
divide(X, Y) ->
{ok, X / Y}.
error_m(E={error, _}, State) ->
fun(bind,_) ->
error_m(E, State);
(return,_) ->
{E, State}
end;
error_m({ok, V}, State) ->
fun(bind, F) ->
F(V, State);
(return,_) ->
{{ok, V}, State}
end;
error_m(V, State) ->
fun(bind, F) ->
F(V, State);
(return,_) ->
{V, State}
end.
maybe(nothing, State) ->
fun(bind,_) ->
maybe(nothing, State);
(return,_) ->
nothing
end;
maybe(V, State) ->
fun(bind, F) ->
F(V, State);
(return,_) ->
{V, State}
end.
identity(X) -> X.
do([InitialOp|Rest]) ->
fun(V, State) ->
R = lists:foldl(
fun(Op, M) ->
M(bind, Op)
end,
InitialOp(V, State),
Rest
),
R(return, '_')
end.
input_example() ->
AssertInt = fun(N, State) when is_integer(N) -> error_m(N, State);
(_, State) -> error_m({error, not_int}, State) end,
F = do([
% Ask for an integer
fun(_, State) ->
Read = io:read("Int> "),
error_m(Read, State) end,
% assert that we read an int
AssertInt,
% Ask for another integer
fun(N1, _) ->
Read = io:read("Int> "),
% keep the first int we read as the state
error_m(Read, N1) end,
% assert the 2nd term we read is an int,
AssertInt,
% Add the two integers together
fun(N2, N1) -> maybe(N2 + N1, '_') end
]),
% execute the operations
F('_', init).
error_example(N) ->
F = do([
fun(X, State) -> error_m(divide(10, X), State) end,
fun(X, State) -> error_m(divide(X, 5), State) end,
fun(X, State) -> maybe(X, State) end
]),
F(N, nostate).
half_example(N) ->
F = do([
fun(X, State) -> maybe(half(X), State) end,
fun(X, State) -> maybe(half(X), State) end,
fun(X, State) -> maybe(half(X), State) end
]),
F(N, nostate).
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment