Last active
March 25, 2017 18:11
-
-
Save shakerlxxv/426871b87859825d334cd9b19018d594 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
%%============================================================================== | |
%% Univ. Kent Functional Programing with Erlang | |
%% Week 3: Part 11 - Functions as results in practice | |
%% | |
%% Description: | |
%% consolidate understanding of functions that take functions as | |
%% arguments and return functions as results. | |
%% | |
%% Author: Brian L. Shaver | |
%% Date : 2017-03-25 | |
%%============================================================================== | |
-module(hof). | |
-include_lib("eunit/include/eunit.hrl"). | |
-export([add/1,times/1,compose/2,id/1,iterate/1,f2ofg2/1,twice/1,composes/1]). | |
%------------------------------------------------------------------------------- | |
% example for same composition either order | |
f1() -> | |
fun _(X) -> X + 1 end. | |
g1() -> | |
fun _(Y) -> Y - 1 end. | |
f1ofg1(X) -> | |
(compose(f1(),g1()))(X). | |
g1off1(Y) -> | |
(compose(g1(),f1()))(Y). | |
compose1_test_() -> | |
[ | |
?_assertEqual(f1ofg1(0),g1off1(0)), | |
?_assertEqual(f1ofg1(9),g1off1(9)) | |
]. | |
%------------------------------------------------------------------------------- | |
% example for different composition other order | |
f2() -> | |
fun _(X) -> X - 1 end. | |
g2() -> | |
fun _(X) -> X * 3 end. | |
f2ofg2(X) -> | |
(compose(f2(),g2()))(X). | |
g2off2(Y) -> | |
(compose(g2(),f2()))(Y). | |
compose2_test() -> | |
% only single counter example required to prove non-commutative | |
?assertNotEqual(f2ofg2(3),g2off2(3)). | |
%------------------------------------------------------------------------------- | |
% function which composes a list of functions | |
composes(L) -> | |
lists:foldr(fun compose/2,fun(Z) -> Z end, L). | |
composes_test_() -> | |
[ | |
?_assertEqual(f2ofg2(3),(composes([f2(),g2()]))(3)), | |
?_assertEqual(f2ofg2(3 + 1),(composes([f1(),f2(),g2()]))(3)), | |
?_assertEqual(f2ofg2(4),(composes([g1(),f1(),f2(),g2()]))(4)) | |
]. | |
%------------------------------------------------------------------------------- | |
% apply a function to itself | |
twice(F) -> | |
compose(F,F). | |
twice_test() -> | |
?assertEqual(18,(twice(g2()))(2)). | |
%------------------------------------------------------------------------------- | |
% apply a function to a function applying a function to itself | |
twice_twice(F) -> | |
(compose(fun twice/1,fun twice/1))(F). | |
twice_twice_test() -> | |
?assertEqual(162,(twice_twice(g2()))(2)). | |
%------------------------------------------------------------------------------- | |
% iterate calling a function N times | |
iterate(0) -> | |
fun(X) -> X end; | |
iterate(N) when N > 0 -> | |
% this version is off by 1 in my opinion because its iterating | |
% one more time for the 0, so iterate(1) is calling the function twice | |
% which I find to be unintuitive. | |
% fun(F) -> compose(F,(iterate(N-1))(F)) end. | |
% credit Giancarlo Valente for the approach below | |
fun(F) -> composes(lists:duplicate(N,F)) end. | |
iterate_test_() -> | |
[ | |
% iterate 1 +1 4 times | |
?_assertEqual(5,((iterate(4))(f1()))(1)), | |
% 4 * 3 * 3 | |
?_assertEqual(36,((iterate(2))(g2()))(4)) | |
]. | |
%------------------------------------------------------------------------------- | |
% hof initial code | |
add(X) -> | |
fun(Y) -> X+Y end. | |
times(X) -> | |
fun(Y) -> | |
X*Y end. | |
compose(F,G) -> | |
fun(X) -> G(F(X)) end. | |
id(X) -> | |
X. |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment