# ``````# Overview

Set of helpers functions for more convenient functional programming on Erlang

Provide following ability:

* currying
* partial applications

## Examples

### Currying

```erlang
Fn = fun(A, B, C, D) ->
A + B + C + D
end,
CFn = erlz:curried(Fn),
10 = (((CFn(1))(2))(3))(4).
```

### Partial application

```erlang
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, ),
[
[1,2,3,4],
[5,6,7,8],
[9,0,1,2],
[3,4,5,6]
]).
```

### do-notation

```erlang
<<"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 ++ } end,
fun( = State) -> {ok, State ++ } end,
fun([1,2] = State) -> {ok, State ++ } end
]).

{error, "reason"} = erlz:error_do([
fun() -> {ok, []} end,
fun([] = State) -> {ok, State ++ } end,
fun( = State) -> {error, "reason"} end,
fun([1,2] = State) -> {ok, State ++ } end
]).
```

### Traversable

Example of traverse on Erlang

```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 that 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

```erlang
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]).
```