an erlang monad?

Ulf Wiger (AL/EAB) <>
Wed Mar 2 16:28:39 CET 2005


I have had reason to do some rather complex code using
a 'dict' dictionary. I find myself constantly wishing
for a library function (and eventually writing it 
myself) that does the following:

with(Dict, Actions) ->
    lists:foldl(fun(F,D) ->
                        F(D)
                end, Dict, Actions).

That is, fold over a list of functions that update
the dictionary. This, I believe, essentially amounts
to a monad in other languages. ;-) Even if this is 
just me misunderstanding monads (like everyone else),
I find the function very useful.

What this does is basically free you from the absurd
D1, D2, D3, etc. gymnastics, where you will eventually,
inevitably mess up the numbering.

An example from my 'builder' module on Jungerl:

    Dict = with(Dict0,
                [fun(D) -> read_options_file(D) end,
                 fun(D) -> store_options(Options, D) end,
                 fun(D) -> post_process_options(D) end,
                 fun(D) ->
                         {Path, [App, Vsn]} = get_app(D),
                         store_options([{app_name, list_to_atom(App)},
                                        {app_vsn, Vsn}], D)
                 end,
                 fun(D) ->
                         [Descr, Id, Reg, Apps, Env, Mod, Phases] =
                             read_app_file(D),
                         Vsn = fetch(app_vsn, D),
                         store_options([{app, [{vsn,Vsn}, Descr, Id, Reg, 
                                               Apps, Env, Mod, Phases]}], D)
                 end,
                 fun(D) -> case dict:find(rel_name, D) of
                               {ok,_} -> D;
                               error ->
                                   RelName = atom_to_list(
                                               fetch(app_name, D)),
                                   dict:store(rel_name, RelName, D)
                           end
                 end,
                 fun(D) -> 
                         RelFname = get_rel_filename(D),
                         case file:consult(RelFname) of
                             {ok, [{release,{_Name,_RelVsn},
                                    _RelApps}= Rel]} ->
                                 ?report(debug,"rel_src = ~p~n",[Rel]),
                                 dict:store(rel_src,Rel, D);
                             _ ->
                                 D
                         end
                 end,
                 fun(D) -> AppInfo = find_apps(D),
                           ?report(debug, "find_apps(D) -> ~p~n", [AppInfo]),
                           dict:store(app_info, AppInfo, D)
                 end,
                 fun(D) ->
                         BootVars = boot_vars(D),
                         dict:store(boot_vars, BootVars, D)
                 end]),



More information about the erlang-questions mailing list