-export(
[ id/1
, curry/1
+ , compose/1 % alias for compose_right/1
+ , compose_right/1
+ , compose_left/1
]).
-spec id(A) ->
apply(F, lists:reverse(Args));
curry(F, Args, Arity) ->
fun (X) -> curry(F, [X | Args], Arity - 1) end.
+
+-spec compose([fun((A) -> B)]) ->
+ fun((A) -> B).
+compose(Fs) ->
+ compose_right(Fs).
+
+-spec compose_right([fun((A) -> B)]) ->
+ fun((A) -> B).
+compose_right(Fs) ->
+ compose_given_fold(Fs, fun lists:foldr/3).
+
+-spec compose_left([fun((A) -> B)]) ->
+ fun((A) -> B).
+compose_left(Fs) ->
+ compose_given_fold(Fs, fun lists:foldl/3).
+
+
+%% ============================================================================
+
+-spec compose_given_fold([fun((A) -> B)], fun((fun((A, B) -> C), B, [A]) -> C)) ->
+ fun((A) -> C).
+compose_given_fold(Fs, Fold) ->
+ fun (X) -> Fold(fun (F, Y) -> F(Y) end, X, Fs) end.
%% Test cases
-export(
- [ t_id/1
+ [ t_specs/1
+ , t_id/1
, t_curry/1
+ , t_compose/1
]).
groups() ->
Tests =
- [ t_id
+ [ t_specs
+ , t_id
, t_curry
+ , t_compose
],
Properties = [parallel],
[ {?GROUP, Properties, Tests}
%% Test cases
%% =============================================================================
+t_specs(_) ->
+ [] = proper:check_specs(hope_fun).
+
t_id(_Cfg) ->
X = foo,
X = hope_fun:id(X).
H2 = H1(a),
H = H2(b),
{a, b, c} = H(c).
+
+t_compose(_Cfg) ->
+ A2B = fun (a) -> b end,
+ B2C = fun (b) -> c end,
+ C2D = fun (c) -> d end,
+ Fs = [C2D, B2C, A2B],
+ d = (hope_fun:compose ( Fs ))(a),
+ d = (hope_fun:compose_right ( Fs ))(a),
+ d = (hope_fun:compose_left (lists:reverse(Fs) ))(a).