23ua/funerl
Maybe and Either monads interfaces in Erlang
{ "createdAt": "2015-11-01T16:14:26Z", "defaultBranch": "master", "description": "Maybe and Either monads interfaces in Erlang", "fullName": "23ua/funerl", "homepage": "", "language": "Erlang", "name": "funerl", "pushedAt": "2015-11-08T00:14:16Z", "stargazersCount": 3, "topics": [ "either", "erlang", "functional-programming", "maybe", "monad", "monadic-interface" ], "updatedAt": "2016-11-29T11:04:15Z", "url": "https://github.com/23ua/funerl"}funerl
Section titled “funerl”What?
Maybe and either monads interfaces based on similar modules in Haskell.
Why?
Just for fun. It was an attempt to solve nested cases “code smell” or “antipattern” in Erlang.
Should I use this library?
Definitely not, just pass on.
Maybe monad
Section titled “Maybe monad”1> Val = maybe:just(1).{ok,1}2> NoVal = maybe:nothing().undefined3> maybe:map(fun(X) -> X+1 end, Val).{ok,2}4> maybe:map(fun(X) -> X+1 end, NoVal).undefinedEither monad
Section titled “Either monad”1> Result = either:right(23).{ok,23}2> Error = either:left(badarg).{error,badarg}3> either:map(fun(X) -> X * 2 end, Result).{ok,46}4> either:map(fun(X) -> X * 2 end, Error).{error,badarg}You can use these monads to handle errors.
Using either:map/2 and either:bind/2 to prevent nested case expressions:
Section titled “Using either:map/2 and either:bind/2 to prevent nested case expressions:”-spec request_order() -> either:either(term()).request_order(Order) -> ... either:right(NewOrder).
-spec validate_order(Order :: term()) -> either:either(term()).validate_order(Order) -> either:left(order_invalid).
-spec db_write(atom(), Order :: term()) -> term().db_write(Table, Value) when is_atom(Table) -> ... Result = db:insert(Table, Value), ... Result;
-spec add_order(term()) -> either:either().add_order(Order) -> Res = request_order(Order), MaybeNewOrder = either:bind(fun validate_order/1, Res),
WriteFun = fun(Ord) -> db_write(order, Ord) end, either:map(WriteFun, MaybeNewOrder).Returns {error, order_invalid}:
1> Order = ...2> Result = add_order(Order).{error, order_invalid}3> either:is_left(Result).true4> either:is_right(Result).false