63 lines
1.8 KiB
Erlang
63 lines
1.8 KiB
Erlang
-module(currying).
|
|
|
|
-compile(export_all).
|
|
|
|
% Function that curry the first or the second argument of a given function of arity 2
|
|
|
|
curry_first(F,X) ->
|
|
fun(Y) -> F(X,Y) end.
|
|
|
|
curry_second(F,Y) ->
|
|
fun(X) -> F(X,Y) end.
|
|
|
|
% Usual curry
|
|
|
|
curry(Fun,Arg) ->
|
|
case erlang:fun_info(Fun,arity) of
|
|
{arity,0} ->
|
|
erlang:error(badarg);
|
|
{arity,ArityFun} ->
|
|
create_ano_fun(ArityFun,Fun,Arg);
|
|
_ ->
|
|
erlang:error(badarg)
|
|
end.
|
|
|
|
create_ano_fun(Arity,Fun,Arg) ->
|
|
Pars =
|
|
[{var,1,list_to_atom(lists:flatten(io_lib:format("X~p", [N])))}
|
|
|| N <- lists:seq(2,Arity)],
|
|
Ano =
|
|
{'fun',1,
|
|
{clauses,[{clause,1,Pars,[],
|
|
[{call,1,{var,1,'Fun'},[{var,1,'Arg'}] ++ Pars}]}]}},
|
|
{_,Result,_} = erl_eval:expr(Ano, [{'Arg',Arg},{'Fun',Fun}]),
|
|
Result.
|
|
|
|
% Generalization of the currying
|
|
|
|
curry_gen(Fun,GivenArgs,PosGivenArgs,PosParArgs) ->
|
|
Pos = PosGivenArgs ++ PosParArgs,
|
|
case erlang:fun_info(Fun,arity) of
|
|
{arity,ArityFun} ->
|
|
case ((length(GivenArgs) + length(PosParArgs)) == ArityFun) and
|
|
(length(GivenArgs) == length(PosGivenArgs)) and
|
|
(length(Pos) == sets:size(sets:from_list(Pos))) of
|
|
true ->
|
|
fun(ParArgs) ->
|
|
case length(ParArgs) == length(PosParArgs) of
|
|
true ->
|
|
Given = lists:zip(PosGivenArgs,GivenArgs),
|
|
Pars = lists:zip(PosParArgs,ParArgs),
|
|
{_,Args} = lists:unzip(lists:sort(Given ++ Pars)),
|
|
erlang:apply(Fun,Args);
|
|
false ->
|
|
erlang:error(badarg)
|
|
end
|
|
end;
|
|
false ->
|
|
erlang:error(badarg)
|
|
end;
|
|
_ ->
|
|
erlang:error(badarg)
|
|
end.
|