Higher Order Modules

ingo.schramm <>
Mon Dec 14 18:13:07 CET 2009


Or strategy? Or OCaml Functors?
:)
Ingo

On Dec 14, 6:08 pm, Zoltan Lajos Kis <> wrote:
> ingo.schramm wrote:
> > I wonder if parameterized modules are really intended to do OOP stuff
> > only. It seems to be possible to use this feature to implement
> > something like higher order modules, modules parameterized by other
> > modules.
>
> > As an example I could write a monoid module like this:
>
> > -module(monoid,[Impl]).
> > -export([op/2,cmp/2,get_id/0,get_member/0,is_member/1,proof/0]).
>
> > %% ------ INTERFACE -----
>
> > % apply monoid operation
> > op(A,B) ->
> >     case members([A,B]) of
> >         true  -> Impl:op(A,B);
> >         false -> undef
> >     end.
>
> > % compare two values if they are equal or not
> > cmp(A,B) ->
> >     case members([A,B]) of
> >         true  -> Impl:cmp(A,B);
> >         false -> undef
> >     end.
>
> > % get the identity or neutral element
> > get_id() ->
> >     Impl:get_id().
>
> > % get an arbitrary member element
> > get_member() ->
> >     Impl:get_member().
>
> > % test whether A is a member or not
> > is_member(A) ->
> >     case Impl:is_member(A) of
> >         true ->
> >             Impl:is_member(Impl:op(A,Impl:get_id()));
> >         false ->
> >             false
> >     end.
>
> > % give proof of monoid laws
> > proof() ->
> >     prove_all()
>
> > %% ------ PRIVATE ------
>
> > prove() ->
> >     I = Impl:get_id(),
> >     A = Impl:get_member(),
> >     B = A,
> >     Op = prove_closed(A,B),
> >     C = op(A,B),
> >     Assoc = prove_assoc(A,B,C),
> >     Id = prove_identity(N,A),
> >     neg(lists:member(false,[Op,Assoc,Id])).
>
> > prove_closed(A,B) ->
> >     Impl:is_member(Impl:op(A,B)).
>
> > prove_assoc(A,B,C) ->
> >     Impl:op(Impl:op(A,B), C) =:= Impl:op(A, Impl:op(B,C)).
>
> > prove_identity(I,A) ->
> >     0 =:= Impl:cmp(A,Impl:op(I,A)).
>
> > neg(true) -> false;
> > neg(false) -> true.
>
> > % empty set is always member
> > members([]) ->
> >     true;
> > members(L = [A|_]) ->
> >     neg(lists:member(false, [ is_member(X) || X <- L])).
>
> > <<<
>
> > Next I could write a module representing the additive monoid of
> > natural numbers (including zero):
>
> > -module(n_add).
> > -export([op/2,cmp/2,get_id/0,get_member/0,is_member/1]).
>
> > op(A,B) ->
> >     A + B.
>
> > cmp(A,B) when A =/= B ->
> >     -1;
> > cmp(A,B) when A =:= B ->
> >     0.
>
> > get_id() ->
> >     0.
>
> > get_member() ->
> >     1.
>
> > is_member(A) when is_integer(A), A < 0 ->
> >     false;
> > is_member(A) when is_integer(A), A >= 0 ->
> >     true;
> > is_member(_A) ->
> >     false.
> > <<<
>
> > And then I use it:
> > ---
> > 1> M = monoid:new(n_add).
> > {monoid,n_add}
> > 2> M:proof().
> > true
> > 3> M:op(1,2).
> > 3
> > ---
>
> > Another implementation may do matrix operations. It is also easy to
> > add more structure, for example to turn the monoid into a group by
> > adding op_inverse/2.
>
> > Does that make any sense?
>
> > Ingo
>
> > ________________________________________________________________
> > erlang-questions mailing list. Seehttp://www.erlang.org/faq.html
> > erlang-questions (at) erlang.org
>
> Smells like the abstract factory pattern. Or is this dependency
> injection ? :-)
>
> Z.
>
> ________________________________________________________________
> erlang-questions mailing list. Seehttp://www.erlang.org/faq.html
> erlang-questions (at) erlang.org


More information about the erlang-questions mailing list