Copy specs from hope_dictionary to allow prop tests
[hope.git] / src / hope_kv_list.erl
... / ...
CommitLineData
1%%%----------------------------------------------------------------------------
2%%% Equivalent to stdlib's orddict, but with a pretty (IMO), uniform interface.
3%%%----------------------------------------------------------------------------
4-module(hope_kv_list).
5
6-behavior(hope_dictionary).
7
8-export_type(
9 [ t/2
10 ]).
11
12-export(
13 [ empty/0
14 , get/2
15 , set/3
16 , update/3
17 , pop/2
18 , iter/2
19 , map/2
20 , filter/2
21 , fold/3
22 , of_kv_list/1
23 , to_kv_list/1
24 ]).
25
26
27-type t(K, V) ::
28 [{K, V}].
29
30
31%% ============================================================================
32%% API
33%% ============================================================================
34
35-spec empty() ->
36 [].
37empty() ->
38 [].
39
40-spec get(t(K, V), K) ->
41 hope_option:t(V).
42get(T, K) ->
43 case lists:keyfind(K, 1, T)
44 of false -> none
45 ; {K, V} -> {some, V}
46 end.
47
48-spec set(t(K, V), K, V) ->
49 t(K, V).
50set(T, K, V) ->
51 lists:keystore(K, 1, T, {K, V}).
52
53-spec update(t(K, V), K, fun((hope_option:t(V)) -> V)) ->
54 t(K, V).
55update(T, K, F) ->
56 V1Opt = get(T, K),
57 V2 = F(V1Opt),
58 % TODO: Eliminate the 2nd lookup.
59 set(T, K, V2).
60
61-spec pop(t(K, V), K) ->
62 {hope_option:t(V), t(K, V)}.
63pop(T1, K) ->
64 case lists:keytake(K, 1, T1)
65 of {value, {K, V}, T2} -> {{some, V}, T2}
66 ; false -> {none , T1}
67 end.
68
69-spec iter(t(K, V), fun((K, V) -> ok)) ->
70 ok.
71iter(T, F1) ->
72 F2 = lift_map(F1),
73 lists:foreach(F2, T).
74
75-spec map(t(K, V), fun((K, V) -> V)) ->
76 t(K, V).
77map(T, F1) ->
78 F2 = fun ({K, _}=X) -> {K, apply_map(F1, X)} end,
79 lists:map(F2, T).
80
81-spec filter(t(K, V), fun((K, V) -> boolean())) ->
82 t(K, V).
83filter(T, F1) ->
84 F2 = lift_map(F1),
85 lists:filter(F2, T).
86
87-spec fold(t(K, V), fun((K, V, Acc) -> Acc), Acc) ->
88 Acc.
89fold(T, F1, Accumulator) ->
90 F2 = fun ({K, V}, Acc) -> F1(K, V, Acc) end,
91 lists:foldl(F2, Accumulator, T).
92
93-spec to_kv_list(t(K, V)) ->
94 [{K, V}].
95to_kv_list(T) ->
96 T.
97
98-spec of_kv_list([{K, V}]) ->
99 t(K, V).
100of_kv_list(List) ->
101 % TODO: Decide if validation is to be done here. Do so if yes.
102 List.
103
104
105%% ============================================================================
106%% Helpers
107%% ============================================================================
108
109-spec lift_map(F) ->
110 G
111 when F :: fun(( K, V1 ) -> V2)
112 , G :: fun(({K, V1}) -> V2)
113 .
114lift_map(F) ->
115 fun (X) -> apply_map(F, X) end.
116
117-spec apply_map(fun((K, V1) -> V2), {K, V1}) ->
118 V2.
119apply_map(F, {K, V}) ->
120 F(K, V).
This page took 0.016527 seconds and 4 git commands to generate.