-module(fluoresce). -compile([no_auto_import, nowarn_unused_vars, nowarn_unused_function, nowarn_nomatch]). -export([compose/2, wrap/1, bind/2, join/1, co/2, callcc/1, apply/2, throw/2]). -export_type([cont/2]). -type cont(FQU, FQV) :: {cont, fun((fun((FQV) -> FQU)) -> FQU)}. -spec compose(fun((FRD) -> FRE), fun((FRF) -> FRD)) -> fun((FRF) -> FRE). compose(F, G) -> fun(X) -> F(G(X)) end. -spec wrap(FRG) -> cont(any(), FRG). wrap(A) -> {cont, fun(K) -> K(A) end}. -spec bind(cont(FRK, FRL), fun((FRL) -> cont(FRK, FRO))) -> cont(FRK, FRO). bind(C, F) -> {cont, fun(K) -> (erlang:element(2, C))(fun(A) -> (erlang:element(2, F(A)))(K) end) end}. -spec join(cont(FRT, cont(FRT, FRU))) -> cont(FRT, FRU). join(A) -> {cont, fun(K) -> (erlang:element(2, A))(fun(B) -> (erlang:element(2, B))(K) end) end}. -spec co( fun((fun((FSC) -> FSB)) -> cont(FSB, FSF)), fun(({ok, FSF} | {error, FSC}) -> cont(FSB, FSK)) ) -> cont(FSB, FSK). co(F, Rest) -> {cont, fun(K) -> K2 = fun(A) -> (erlang:element(2, Rest(A)))(K) end, (erlang:element( 2, F(compose(K2, fun(Field@0) -> {error, Field@0} end)) ))(compose(K2, fun(Field@0) -> {ok, Field@0} end)) end}. -spec callcc(fun((fun((FSQ) -> FSP)) -> FSQ)) -> cont(FSP, FSQ). callcc(F) -> co(fun(K) -> wrap(F(K)) end, fun(S) -> _pipe = case S of {error, A} -> A; {ok, A@1} -> A@1 end, wrap(_pipe) end). -spec apply(cont(FSV, {ok, FSW} | {error, FSX}), fun((FSX) -> FSV)) -> cont(FSV, FSW). apply(E, Not_a) -> {cont, fun(K) -> (erlang:element(2, E))(fun(Res) -> case Res of {error, A} -> Not_a(A); {ok, E@1} -> K(E@1) end end) end}. -spec throw(FTG, fun((FTG) -> FTH)) -> cont(FTH, any()). throw(A, Not_a) -> Instant_fail = wrap({error, A}), apply(Instant_fail, Not_a).