Created
January 25, 2012 04:46
-
-
Save jwthomp/1674783 to your computer and use it in GitHub Desktop.
Erlang Monad
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-module(monad). | |
-export([ monad_context/2, putst/1, getst/0, lift/0, return/1 ]). | |
-export([ test/0 ]). | |
%%%%%%%%%%%%%%%%%%%%% Erlang Monad %%%%%%%%%%%%%%%%%%%%%% | |
%% Working on a simple monad implementation for Erlang %% | |
%% %% | |
%% Just for fun I tried whipping up a simple erlang %% | |
%% monad. It uses the process dictionary and I haven't %% | |
%% implemented lift and many children of a monad state %% | |
%% yet. Otherwise it works (with minor testing). %% | |
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% | |
test() -> test(0). | |
test(State) -> | |
_Fun1 = fun(_X) -> | |
S = getst(), | |
S + 2 | |
end, | |
_Fun2 = fun(X) -> | |
S = getst(), | |
putst(X * 2), | |
return(S) | |
end, | |
monad_context([fun add2ToState/1, fun mul2/1, fun store_ret/1 ], State). | |
add2ToState(_X) -> S = getst(), S + 2. | |
mul2(X) -> X * 2. | |
store_ret(X) -> putst(X), return(X). | |
monad_context(FunList, InitialState) -> | |
push_monad(InitialState), | |
do_runner(nil, FunList). | |
%% Put state | |
putst(State) -> put_state(State). | |
%% Get state | |
getst() -> get_state(). | |
%%%%%% TODO %%%%%% | |
%% Lift up a state | |
lift() -> ok. | |
return(X) -> {return, {X, pop_monad()}}. | |
%% Internal %% | |
push_monad(InitialState) -> | |
case get(monad_state) of | |
undefined -> State = []; | |
State -> ok | |
end, | |
put(monad_state, [InitialState | State]), | |
[InitialState | State]. | |
pop_monad() -> | |
[State | Rest] = get(monad_state), | |
put(monad_state, Rest), | |
State. | |
get_state() -> | |
[State | _Rest] = get(monad_state), | |
State. | |
put_state(State) -> | |
[_StateOld | Rest] = get(monad_state), | |
put(monad_state, [State | Rest]). | |
do_runner({return, {X, State}}, _) -> {ok, {X, State}}; | |
do_runner(_X, []) -> {error, no_return}; | |
do_runner(X, [Fun | RestFuns]) -> | |
X2 = Fun(X), | |
do_runner(X2, RestFuns). |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-module(monad2). | |
%-export([ bind/2, return/1, get/0, put/1, runstate/2 ]). | |
-export([ bind/2, bind_/2, return/1, run/1, raise/1 ]). | |
% error monad {status, value} | |
% status = error | ok | |
% M = {state, Value} | |
% F(M) -> M' | |
% M() -> Mdata | |
% runstate(bind(get(), fun(X) -> put(X+1) end), 1) | |
%%FMAP | |
%% Take a function T (and Transformer) and wrap it into our monad | |
%% so that we can transform results | |
% T => function like tolower(X) | |
% M => X | |
% fmap(T,M) -> M' | |
fmap(T, M) -> | |
bind(M, fun(X) -> return(T(X)) end). | |
%% EXCEPTION HANDLER | |
bind(M,F) -> | |
fun() -> | |
case M() of | |
{ok, X} -> (F(X))(); | |
{error, Reason} -> {error, Reason} | |
end | |
end. | |
bind_(M1, M2) -> bind(M1, fun(_) -> M2 end). | |
raise(X) -> fun() -> {error, X} end. | |
return(X) -> fun() -> {ok, X} end. | |
run(M) -> M(). | |
%% STATE | |
%% bind from one parse combinator to the next | |
%bind (M,F) -> | |
% fun (ST) -> | |
% case M(ST) of | |
% {X,NewState} -> (F(X))({ok,NewState}); | |
% Error -> Error | |
% end | |
% end. | |
%return(X) -> | |
% fun ({_, State}) -> {X, State} ; | |
% (Error) -> Error | |
% end. | |
% State monad | |
%get() -> | |
% fun({_, State}) -> {State, State} end. | |
%put(NewState) -> | |
% fun({_,_}) -> {ok, NewState} end. | |
%runstate(M, State) -> | |
% M({undefined, State}). |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment