Define and implement a generic monad behavior.
[hope.git] / src / hope_result.erl
... / ...
CommitLineData
1-module(hope_result).
2
3-behavior(hope_monad).
4
5-export_type(
6 [ t/2
7 ]).
8
9-export(
10 [ return/1
11 , map/2
12 , pipe/2
13 , lift_exn/1
14 , lift_exn/2
15 ]).
16
17
18-type t(A, B) ::
19 {ok, A}
20 | {error, B}
21 .
22
23
24-spec return(A) ->
25 {ok, A}.
26return(X) ->
27 {ok, X}.
28
29-spec map(t(A, Error), fun((A) -> (B))) ->
30 t(B, Error).
31map({ok, X}, F) ->
32 {ok, F(X)};
33map({error, _}=Error, _) ->
34 Error.
35
36-spec pipe([F], X) ->
37 t(Ok, Error)
38 when X :: any()
39 , Ok :: any()
40 , Error :: any()
41 , F :: fun((X) -> t(Ok, Error))
42 .
43pipe([], X) ->
44 {ok, X};
45pipe([F|Fs], X) ->
46 case F(X)
47 of {error, _}=E -> E
48 ; {ok, Y} -> pipe(Fs, Y)
49 end.
50
51-spec lift_exn(F) -> G
52 when F :: fun((A)-> B)
53 , G :: fun((A)-> t(B, {Class, Reason :: any()}))
54 , Class :: error
55 | exit
56 | throw
57 .
58lift_exn(F) when is_function(F, 1) ->
59 fun(X) ->
60 try
61 {ok, F(X)}
62 catch Class:Reason ->
63 {error, {Class, Reason}}
64 end
65 end.
66
67-spec lift_exn(F, Label) -> G
68 when F :: fun((A)-> B)
69 , G :: fun((A)-> t(B, {Label, {Class, Reason :: any()}}))
70 , Class :: error
71 | exit
72 | throw
73 .
74lift_exn(F, Label) when is_function(F, 1) ->
75 fun(X) ->
76 try
77 {ok, F(X)}
78 catch Class:Reason ->
79 {error, {Label, {Class, Reason}}}
80 end
81 end.
This page took 0.024263 seconds and 4 git commands to generate.