X-Git-Url: https://git.xandkar.net/?a=blobdiff_plain;f=src%2Fhope_option.erl;h=c645c5388d63e0472c8eba6ce58af7d8ec8753cf;hb=0ed4baebe135edc50d24d3613c6ee971f75d8c98;hp=622c06df92fd59b2df7df5c3a1e80aba8876fe65;hpb=2a40de4f9404d67967ad486d7d10b354791105fe;p=hope.git diff --git a/src/hope_option.erl b/src/hope_option.erl index 622c06d..c645c53 100644 --- a/src/hope_option.erl +++ b/src/hope_option.erl @@ -1,14 +1,25 @@ -module(hope_option). +-behavior(hope_gen_monad). -export_type( [ t/1 ]). -export( - [ put/2 - , get/2 + % Generic monad interface + [ return/1 , map/2 + , pipe/2 + + % Specific to hope_option:t() + , return/2 + , put/2 + , get/2 + , iter/2 + , of_result/1 + , of_undefined/1 + , validate/2 ]). @@ -18,14 +29,68 @@ . +-spec put(A, fun((A) -> boolean())) -> + t(A). put(X, F) -> - case F(X) - of true -> {some, X} - ; false -> none - end. + return(X, F). +-spec get(t(A), Default :: A) -> + A. get({some, X}, _) -> X; get(none , Y) -> Y. +-spec return(A) -> + {some, A}. +return(X) -> + {some, X}. + +-spec return(A, fun((A) -> boolean())) -> + t(A). +return(X, Condition) -> + case Condition(X) + of true -> {some, X} + ; false -> none + end. + +-spec map(t(A), fun((A) -> (B))) -> + t(B). map({some, X}, F) -> {some, F(X)}; map(none , _) -> none. + +-spec iter(t(A), fun((A) -> (any()))) -> + ok. +iter({some, X}, F) -> + _ = F(X), + ok; +iter(none, _) -> + ok. + +-spec pipe([fun((A) -> t(B))], A) -> + t(B). +pipe([], X) -> + return(X); +pipe([F|Fs], X) -> + case F(X) + of none -> none + ; {some, Y} -> pipe(Fs, Y) + end. + +-spec of_result(hope_result:t(A, _B)) -> + t(A). +of_result({ok, X}) -> {some, X}; +of_result({error, _}) -> none. + +-spec of_undefined(undefined | A) -> + t(A). +of_undefined(undefined) -> none; +of_undefined(X) -> {some, X}. + +-spec validate(t(A), fun((A) -> boolean())) -> + t(A). +validate(none, _) -> + none; +validate({some, X}=T, F) -> + case F(X) + of false -> none + ; true -> T + end.