From 0b6ed6177fd85b5dd1b6ceadb9c2e2560c6597d2 Mon Sep 17 00:00:00 2001 From: Siraaj Khandkar Date: Fri, 1 May 2015 15:59:31 -0400 Subject: [PATCH] Implement function composition. --- src/hope.app.src | 2 +- src/hope_fun.erl | 26 ++++++++++++++++++++++++++ test/hope_fun_SUITE.erl | 20 ++++++++++++++++++-- 3 files changed, 45 insertions(+), 3 deletions(-) diff --git a/src/hope.app.src b/src/hope.app.src index 1ac246a..197db7c 100644 --- a/src/hope.app.src +++ b/src/hope.app.src @@ -1,7 +1,7 @@ {application, hope, [ {description, "Higher Order Programming in Erlang"}, - {vsn, "3.1.1"}, + {vsn, "3.2.0"}, {registered, []}, {applications, [ kernel, diff --git a/src/hope_fun.erl b/src/hope_fun.erl index c2443ce..96a39cd 100644 --- a/src/hope_fun.erl +++ b/src/hope_fun.erl @@ -3,6 +3,9 @@ -export( [ id/1 , curry/1 + , compose/1 % alias for compose_right/1 + , compose_right/1 + , compose_left/1 ]). -spec id(A) -> @@ -22,3 +25,26 @@ curry(F, Args, 0) -> 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. diff --git a/test/hope_fun_SUITE.erl b/test/hope_fun_SUITE.erl index 910cc49..7b5051b 100644 --- a/test/hope_fun_SUITE.erl +++ b/test/hope_fun_SUITE.erl @@ -8,8 +8,10 @@ %% Test cases -export( - [ t_id/1 + [ t_specs/1 + , t_id/1 , t_curry/1 + , t_compose/1 ]). @@ -26,8 +28,10 @@ all() -> groups() -> Tests = - [ t_id + [ t_specs + , t_id , t_curry + , t_compose ], Properties = [parallel], [ {?GROUP, Properties, Tests} @@ -38,6 +42,9 @@ groups() -> %% Test cases %% ============================================================================= +t_specs(_) -> + [] = proper:check_specs(hope_fun). + t_id(_Cfg) -> X = foo, X = hope_fun:id(X). @@ -58,3 +65,12 @@ t_curry(_Cfg) -> 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). -- 2.20.1