erlz
erlz copied to clipboard
Set of helpers functions for more convenient functional programming in Erlang
Overview
Set of helpers functions for more convenient functional programming on Erlang
Provide following ability:
- currying
- partial applications
- simplest monadic computation
Examples
Currying
Fn = fun(A, B, C, D) ->
A + B + C + D
end,
CFn = erlz:curried(Fn),
10 = (((CFn(1))(2))(3))(4).
Partial application
Fn = fun(A, B, C, D, E) ->
1 = A,
2 = B,
3 = C,
4 = D,
5 = E,
A + B + C + D + E
end,
% Atom '_' is used for specifying place where value must be substituted
PFn = erlz:partial(Fn, [1, '_', '_', 4, 5]),
{arity, 2} = erlang:fun_info(PFn, arity),
15 = PFn(2, 3).
[3,7,1,5] = lists:map(
erlz:partial(fun lists:nth/2, [3]),
[
[1,2,3,4],
[5,6,7,8],
[9,0,1,2],
[3,4,5,6]
]).
do-notation
<<"16.0">> = erlz:do(0, [
fun(X) -> X+1 end,
fun(X) -> X+3 end,
% using currying
(erlz:curried(fun math:pow/2))(2),
erlz:partial(
fun erlang:float_to_binary/2,
['_', [{decimals, 4}, compact]])
]).
{left,{stop,1}} = erlz:either_do(0, [
fun(X) -> {right, X+1} end,
fun(X) -> {left, {stop, X}} end,
fun(X) -> {right, X+100} end
]).
{ok, [1,2,3]} = erlz:error_do([
fun() -> {ok, []} end,
fun([] = State) -> {ok, State ++ [1]} end,
fun([1] = State) -> {ok, State ++ [2]} end,
fun([1,2] = State) -> {ok, State ++ [3]} end
]).
{error, "reason"} = erlz:error_do([
fun() -> {ok, []} end,
fun([] = State) -> {ok, State ++ [1]} end,
fun([1] = State) -> {error, "reason"} end,
fun([1,2] = State) -> {ok, State ++ [3]} end
]).
Traversable
Example of traverse on Erlang
Fn = fun(Item) ->
case Item > 5 of
true -> {left, "Contains value greater than 5"};
_ -> {right, Item * 2}
end
end,
{left,"Contains value greater than 5"} = erlz:either_traverse(Fn, [6,1,2,3,4]).
{right,[2,4,6,8]} = erlz:either_traverse(Fn, [1,2,3,4]).
A similar example as above but on Haskell
> (traverse
(\x -> if x > 5 then Left ("Contains value greater than 5") else Right (x * 2))
[6, 1..5])
Left "Contains value greater than 5"
> (traverse
(\x -> if x > 5 then Left ("Contains value greater than 5") else Right (x * 2))
[1..5])
Right [2,4,6,8,10]
foldM
Simple example
Fn = fun(X, Sum) ->
case X > 5 of
true -> {left, "Contains value greater than 5"};
_ -> {right, Sum + X}
end
end,
{right,3} = erlz:either_foldlM(Fn, 0, [1,1,1]),
{left,"Contains value greater than 5"} = erlz:either_foldlM(Fn, 0, [6,1,1]).
and analogue on Haskell
> let f = (\acc x -> if x > 5 then Left ("Contains value greater than 5") else Right (acc + x)) in foldlM f 0 [1,1,1]
Right 3
> let f = (\acc x -> if x > 5 then Left ("Contains value greater than 5") else Right (acc + x)) in foldlM f 0 [6,1,1]
Left "Contains value greater than 5"