Higher Order Modules
ingo.schramm
schramm.ingo@REDACTED
Mon Dec 14 18:13:07 CET 2009
Or strategy? Or OCaml Functors?
:)
Ingo
On Dec 14, 6:08 pm, Zoltan Lajos Kis <ki...@REDACTED> 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