author | wenzelm |
Thu, 07 Apr 2005 09:26:40 +0200 | |
changeset 15665 | 7e7412fffc0c |
parent 15574 | b1d1b5bfc464 |
child 15761 | c9561302c74a |
permissions | -rw-r--r-- |
6118 | 1 |
(* Title: Pure/General/table.ML |
5015 | 2 |
ID: $Id$ |
15014 | 3 |
Author: Markus Wenzel and Stefan Berghofer, TU Muenchen |
5015 | 4 |
|
8806 | 5 |
Generic tables and tables indexed by strings. Efficient purely |
15014 | 6 |
functional implementation using balanced 2-3 trees. |
5015 | 7 |
*) |
8 |
||
9 |
signature KEY = |
|
10 |
sig |
|
11 |
type key |
|
12 |
val ord: key * key -> order |
|
13 |
end; |
|
14 |
||
15 |
signature TABLE = |
|
16 |
sig |
|
17 |
type key |
|
18 |
type 'a table |
|
19 |
exception DUP of key |
|
20 |
exception DUPS of key list |
|
15014 | 21 |
exception UNDEF of key |
5015 | 22 |
val empty: 'a table |
23 |
val is_empty: 'a table -> bool |
|
5681 | 24 |
val map: ('a -> 'b) -> 'a table -> 'b table |
25 |
val foldl: ('a * (key * 'b) -> 'a) -> 'a * 'b table -> 'a |
|
5015 | 26 |
val dest: 'a table -> (key * 'a) list |
5681 | 27 |
val keys: 'a table -> key list |
8409 | 28 |
val min_key: 'a table -> key option |
15160 | 29 |
val max_key: 'a table -> key option |
7061 | 30 |
val exists: (key * 'a -> bool) -> 'a table -> bool |
5015 | 31 |
val lookup: 'a table * key -> 'a option |
32 |
val update: (key * 'a) * 'a table -> 'a table |
|
12287 | 33 |
val update_new: (key * 'a) * 'a table -> 'a table (*exception DUP*) |
15665 | 34 |
val map_entry: key -> ('a -> 'a) -> 'a table -> 'a table |
12287 | 35 |
val make: (key * 'a) list -> 'a table (*exception DUPS*) |
36 |
val extend: 'a table * (key * 'a) list -> 'a table (*exception DUPS*) |
|
37 |
val join: ('a * 'a -> 'a option) -> 'a table * 'a table -> 'a table (*exception DUPS*) |
|
38 |
val merge: ('a * 'a -> bool) -> 'a table * 'a table -> 'a table (*exception DUPS*) |
|
15665 | 39 |
val delete: key -> 'a table -> 'a table (*exception UNDEF*) |
5015 | 40 |
val lookup_multi: 'a list table * key -> 'a list |
8606 | 41 |
val update_multi: (key * 'a) * 'a list table -> 'a list table |
5015 | 42 |
val make_multi: (key * 'a) list -> 'a list table |
43 |
val dest_multi: 'a list table -> (key * 'a) list |
|
12287 | 44 |
val merge_multi: ('a * 'a -> bool) -> |
45 |
'a list table * 'a list table -> 'a list table (*exception DUPS*) |
|
46 |
val merge_multi': ('a * 'a -> bool) -> |
|
47 |
'a list table * 'a list table -> 'a list table (*exception DUPS*) |
|
5015 | 48 |
end; |
49 |
||
50 |
functor TableFun(Key: KEY): TABLE = |
|
51 |
struct |
|
52 |
||
53 |
||
54 |
(* datatype table *) |
|
55 |
||
56 |
type key = Key.key; |
|
57 |
||
58 |
datatype 'a table = |
|
59 |
Empty | |
|
60 |
Branch2 of 'a table * (key * 'a) * 'a table | |
|
61 |
Branch3 of 'a table * (key * 'a) * 'a table * (key * 'a) * 'a table; |
|
62 |
||
63 |
exception DUP of key; |
|
64 |
exception DUPS of key list; |
|
65 |
||
66 |
||
5681 | 67 |
(* empty *) |
68 |
||
5015 | 69 |
val empty = Empty; |
70 |
||
71 |
fun is_empty Empty = true |
|
72 |
| is_empty _ = false; |
|
73 |
||
5681 | 74 |
|
75 |
(* map and fold combinators *) |
|
76 |
||
77 |
fun map_table _ Empty = Empty |
|
78 |
| map_table f (Branch2 (left, (k, x), right)) = |
|
79 |
Branch2 (map_table f left, (k, f x), map_table f right) |
|
80 |
| map_table f (Branch3 (left, (k1, x1), mid, (k2, x2), right)) = |
|
81 |
Branch3 (map_table f left, (k1, f x1), map_table f mid, (k2, f x2), map_table f right); |
|
82 |
||
83 |
fun foldl_table _ (x, Empty) = x |
|
84 |
| foldl_table f (x, Branch2 (left, p, right)) = |
|
85 |
foldl_table f (f (foldl_table f (x, left), p), right) |
|
86 |
| foldl_table f (x, Branch3 (left, p1, mid, p2, right)) = |
|
87 |
foldl_table f (f (foldl_table f (f (foldl_table f (x, left), p1), mid), p2), right); |
|
88 |
||
89 |
fun dest tab = rev (foldl_table (fn (rev_ps, p) => p :: rev_ps) ([], tab)); |
|
90 |
fun keys tab = rev (foldl_table (fn (rev_ks, (k, _)) => k :: rev_ks) ([], tab)); |
|
7061 | 91 |
fun exists P tab = foldl_table (fn (false, e) => P e | (b, _) => b) (false, tab); |
5015 | 92 |
|
15531 | 93 |
fun min_key Empty = NONE |
15665 | 94 |
| min_key (Branch2 (left, (k, _), _)) = SOME (getOpt (min_key left, k)) |
95 |
| min_key (Branch3 (left, (k, _), _, _, _)) = SOME (getOpt (min_key left, k)); |
|
8409 | 96 |
|
15531 | 97 |
fun max_key Empty = NONE |
15665 | 98 |
| max_key (Branch2 (_, (k, _), right)) = SOME (getOpt (max_key right, k)) |
99 |
| max_key (Branch3 (_, _, _, (k,_), right)) = SOME (getOpt (max_key right, k)); |
|
100 |
||
5015 | 101 |
|
102 |
(* lookup *) |
|
103 |
||
15531 | 104 |
fun lookup (Empty, _) = NONE |
5015 | 105 |
| lookup (Branch2 (left, (k, x), right), key) = |
106 |
(case Key.ord (key, k) of |
|
107 |
LESS => lookup (left, key) |
|
15531 | 108 |
| EQUAL => SOME x |
5015 | 109 |
| GREATER => lookup (right, key)) |
110 |
| lookup (Branch3 (left, (k1, x1), mid, (k2, x2), right), key) = |
|
111 |
(case Key.ord (key, k1) of |
|
112 |
LESS => lookup (left, key) |
|
15531 | 113 |
| EQUAL => SOME x1 |
5015 | 114 |
| GREATER => |
115 |
(case Key.ord (key, k2) of |
|
116 |
LESS => lookup (mid, key) |
|
15531 | 117 |
| EQUAL => SOME x2 |
5015 | 118 |
| GREATER => lookup (right, key))); |
119 |
||
120 |
||
15665 | 121 |
(* updates *) |
5015 | 122 |
|
15665 | 123 |
local |
124 |
||
125 |
exception SAME; |
|
5015 | 126 |
|
127 |
datatype 'a growth = |
|
128 |
Stay of 'a table | |
|
129 |
Sprout of 'a table * (key * 'a) * 'a table; |
|
130 |
||
15665 | 131 |
fun modify key f tab = |
132 |
let |
|
133 |
fun modfy Empty = Sprout (Empty, (key, f NONE), Empty) |
|
134 |
| modfy (Branch2 (left, p as (k, x), right)) = |
|
135 |
(case Key.ord (key, k) of |
|
136 |
LESS => |
|
137 |
(case modfy left of |
|
138 |
Stay left' => Stay (Branch2 (left', p, right)) |
|
139 |
| Sprout (left1, q, left2) => Stay (Branch3 (left1, q, left2, p, right))) |
|
140 |
| EQUAL => Stay (Branch2 (left, (k, f (SOME x)), right)) |
|
141 |
| GREATER => |
|
142 |
(case modfy right of |
|
143 |
Stay right' => Stay (Branch2 (left, p, right')) |
|
144 |
| Sprout (right1, q, right2) => |
|
145 |
Stay (Branch3 (left, p, right1, q, right2)))) |
|
146 |
| modfy (Branch3 (left, p1 as (k1, x1), mid, p2 as (k2, x2), right)) = |
|
147 |
(case Key.ord (key, k1) of |
|
5015 | 148 |
LESS => |
15665 | 149 |
(case modfy left of |
150 |
Stay left' => Stay (Branch3 (left', p1, mid, p2, right)) |
|
151 |
| Sprout (left1, q, left2) => |
|
152 |
Sprout (Branch2 (left1, q, left2), p1, Branch2 (mid, p2, right))) |
|
153 |
| EQUAL => Stay (Branch3 (left, (k1, f (SOME x1)), mid, p2, right)) |
|
5015 | 154 |
| GREATER => |
15665 | 155 |
(case Key.ord (key, k2) of |
156 |
LESS => |
|
157 |
(case modfy mid of |
|
158 |
Stay mid' => Stay (Branch3 (left, p1, mid', p2, right)) |
|
159 |
| Sprout (mid1, q, mid2) => |
|
160 |
Sprout (Branch2 (left, p1, mid1), q, Branch2 (mid2, p2, right))) |
|
161 |
| EQUAL => Stay (Branch3 (left, p1, mid, (k2, f (SOME x2)), right)) |
|
162 |
| GREATER => |
|
163 |
(case modfy right of |
|
164 |
Stay right' => Stay (Branch3 (left, p1, mid, p2, right')) |
|
165 |
| Sprout (right1, q, right2) => |
|
166 |
Sprout (Branch2 (left, p1, mid), p2, Branch2 (right1, q, right2))))); |
|
5015 | 167 |
|
15665 | 168 |
in |
169 |
(case modfy tab of |
|
170 |
Stay tab' => tab' |
|
171 |
| Sprout br => Branch2 br) |
|
172 |
handle SAME => tab |
|
173 |
end; |
|
5015 | 174 |
|
15665 | 175 |
in |
176 |
||
177 |
fun update ((k, x), tab) = modify k (fn _ => x) tab; |
|
178 |
fun update_new ((k, x), tab) = modify k (fn NONE => x | SOME _ => raise DUP k) tab; |
|
179 |
fun map_entry k f = modify k (fn NONE => raise SAME | SOME x => f x); |
|
180 |
||
181 |
end; |
|
5015 | 182 |
|
183 |
||
12287 | 184 |
(* extend and make *) |
5015 | 185 |
|
12287 | 186 |
fun extend (table, pairs) = |
187 |
let |
|
188 |
fun add ((tab, dups), (key, x)) = |
|
189 |
(case lookup (tab, key) of |
|
15531 | 190 |
NONE => (update ((key, x), tab), dups) |
12287 | 191 |
| _ => (tab, key :: dups)); |
192 |
in |
|
15570 | 193 |
(case Library.foldl add ((table, []), pairs) of |
12287 | 194 |
(table', []) => table' |
195 |
| (_, dups) => raise DUPS (rev dups)) |
|
196 |
end; |
|
197 |
||
198 |
fun make pairs = extend (empty, pairs); |
|
199 |
||
5015 | 200 |
|
15014 | 201 |
(* delete *) |
202 |
||
15665 | 203 |
exception UNDEF of key; |
204 |
||
205 |
local |
|
206 |
||
207 |
fun compare NONE (k2, _) = LESS |
|
208 |
| compare (SOME k1) (k2, _) = Key.ord (k1, k2); |
|
15014 | 209 |
|
210 |
fun if_eq EQUAL x y = x |
|
211 |
| if_eq _ x y = y; |
|
212 |
||
15531 | 213 |
fun del (SOME k) Empty = raise UNDEF k |
214 |
| del NONE (Branch2 (Empty, p, Empty)) = (p, (true, Empty)) |
|
215 |
| del NONE (Branch3 (Empty, p, Empty, q, Empty)) = |
|
15014 | 216 |
(p, (false, Branch2 (Empty, q, Empty))) |
15665 | 217 |
| del k (Branch2 (Empty, p, Empty)) = (case compare k p of |
15570 | 218 |
EQUAL => (p, (true, Empty)) | _ => raise UNDEF (valOf k)) |
15665 | 219 |
| del k (Branch3 (Empty, p, Empty, q, Empty)) = (case compare k p of |
15014 | 220 |
EQUAL => (p, (false, Branch2 (Empty, q, Empty))) |
15665 | 221 |
| _ => (case compare k q of |
15014 | 222 |
EQUAL => (q, (false, Branch2 (Empty, p, Empty))) |
15570 | 223 |
| _ => raise UNDEF (valOf k))) |
15665 | 224 |
| del k (Branch2 (l, p, r)) = (case compare k p of |
15014 | 225 |
LESS => (case del k l of |
226 |
(p', (false, l')) => (p', (false, Branch2 (l', p, r))) |
|
227 |
| (p', (true, l')) => (p', case r of |
|
228 |
Branch2 (rl, rp, rr) => |
|
229 |
(true, Branch3 (l', p, rl, rp, rr)) |
|
230 |
| Branch3 (rl, rp, rm, rq, rr) => (false, Branch2 |
|
231 |
(Branch2 (l', p, rl), rp, Branch2 (rm, rq, rr))))) |
|
15531 | 232 |
| ord => (case del (if_eq ord NONE k) r of |
15014 | 233 |
(p', (false, r')) => (p', (false, Branch2 (l, if_eq ord p' p, r'))) |
234 |
| (p', (true, r')) => (p', case l of |
|
235 |
Branch2 (ll, lp, lr) => |
|
236 |
(true, Branch3 (ll, lp, lr, if_eq ord p' p, r')) |
|
237 |
| Branch3 (ll, lp, lm, lq, lr) => (false, Branch2 |
|
238 |
(Branch2 (ll, lp, lm), lq, Branch2 (lr, if_eq ord p' p, r')))))) |
|
15665 | 239 |
| del k (Branch3 (l, p, m, q, r)) = (case compare k q of |
240 |
LESS => (case compare k p of |
|
15014 | 241 |
LESS => (case del k l of |
242 |
(p', (false, l')) => (p', (false, Branch3 (l', p, m, q, r))) |
|
243 |
| (p', (true, l')) => (p', (false, case (m, r) of |
|
244 |
(Branch2 (ml, mp, mr), Branch2 _) => |
|
245 |
Branch2 (Branch3 (l', p, ml, mp, mr), q, r) |
|
246 |
| (Branch3 (ml, mp, mm, mq, mr), _) => |
|
247 |
Branch3 (Branch2 (l', p, ml), mp, Branch2 (mm, mq, mr), q, r) |
|
248 |
| (Branch2 (ml, mp, mr), Branch3 (rl, rp, rm, rq, rr)) => |
|
249 |
Branch3 (Branch2 (l', p, ml), mp, Branch2 (mr, q, rl), rp, |
|
250 |
Branch2 (rm, rq, rr))))) |
|
15531 | 251 |
| ord => (case del (if_eq ord NONE k) m of |
15014 | 252 |
(p', (false, m')) => |
253 |
(p', (false, Branch3 (l, if_eq ord p' p, m', q, r))) |
|
254 |
| (p', (true, m')) => (p', (false, case (l, r) of |
|
255 |
(Branch2 (ll, lp, lr), Branch2 _) => |
|
256 |
Branch2 (Branch3 (ll, lp, lr, if_eq ord p' p, m'), q, r) |
|
257 |
| (Branch3 (ll, lp, lm, lq, lr), _) => |
|
258 |
Branch3 (Branch2 (ll, lp, lm), lq, |
|
259 |
Branch2 (lr, if_eq ord p' p, m'), q, r) |
|
260 |
| (_, Branch3 (rl, rp, rm, rq, rr)) => |
|
261 |
Branch3 (l, if_eq ord p' p, Branch2 (m', q, rl), rp, |
|
262 |
Branch2 (rm, rq, rr)))))) |
|
15531 | 263 |
| ord => (case del (if_eq ord NONE k) r of |
15014 | 264 |
(q', (false, r')) => |
265 |
(q', (false, Branch3 (l, p, m, if_eq ord q' q, r'))) |
|
266 |
| (q', (true, r')) => (q', (false, case (l, m) of |
|
267 |
(Branch2 _, Branch2 (ml, mp, mr)) => |
|
268 |
Branch2 (l, p, Branch3 (ml, mp, mr, if_eq ord q' q, r')) |
|
269 |
| (_, Branch3 (ml, mp, mm, mq, mr)) => |
|
270 |
Branch3 (l, p, Branch2 (ml, mp, mm), mq, |
|
271 |
Branch2 (mr, if_eq ord q' q, r')) |
|
272 |
| (Branch3 (ll, lp, lm, lq, lr), Branch2 (ml, mp, mr)) => |
|
273 |
Branch3 (Branch2 (ll, lp, lm), lq, Branch2 (lr, p, ml), mp, |
|
274 |
Branch2 (mr, if_eq ord q' q, r')))))); |
|
275 |
||
15665 | 276 |
in |
277 |
||
15531 | 278 |
fun delete k t = snd (snd (del (SOME k) t)); |
15014 | 279 |
|
15665 | 280 |
end; |
281 |
||
15014 | 282 |
|
12287 | 283 |
(* join and merge *) |
5015 | 284 |
|
12287 | 285 |
fun join f (table1, table2) = |
286 |
let |
|
287 |
fun add ((tab, dups), (key, x)) = |
|
288 |
(case lookup (tab, key) of |
|
15531 | 289 |
NONE => (update ((key, x), tab), dups) |
290 |
| SOME y => |
|
12287 | 291 |
(case f (y, x) of |
15531 | 292 |
SOME z => (update ((key, z), tab), dups) |
293 |
| NONE => (tab, key :: dups))); |
|
12287 | 294 |
in |
295 |
(case foldl_table add ((table1, []), table2) of |
|
296 |
(table', []) => table' |
|
297 |
| (_, dups) => raise DUPS (rev dups)) |
|
298 |
end; |
|
299 |
||
15531 | 300 |
fun merge eq tabs = join (fn (y, x) => if eq (y, x) then SOME y else NONE) tabs; |
5015 | 301 |
|
302 |
||
303 |
(* tables with multiple entries per key (preserving order) *) |
|
304 |
||
15570 | 305 |
fun lookup_multi tab_key = getOpt (lookup tab_key,[]); |
12287 | 306 |
fun update_multi ((key, x), tab) = update ((key, x :: lookup_multi (tab, key)), tab); |
5015 | 307 |
|
15574
b1d1b5bfc464
Removed practically all references to Library.foldr.
skalberg
parents:
15570
diff
changeset
|
308 |
fun make_multi pairs = foldr update_multi empty pairs; |
15570 | 309 |
fun dest_multi tab = List.concat (map (fn (key, xs) => map (Library.pair key) xs) (dest tab)); |
15531 | 310 |
fun merge_multi eq tabs = join (fn (xs, xs') => SOME (gen_merge_lists eq xs xs')) tabs; |
311 |
fun merge_multi' eq tabs = join (fn (xs, xs') => SOME (gen_merge_lists' eq xs xs')) tabs; |
|
5015 | 312 |
|
313 |
||
5681 | 314 |
(*final declarations of this structure!*) |
315 |
val map = map_table; |
|
316 |
val foldl = foldl_table; |
|
5015 | 317 |
|
318 |
end; |
|
319 |
||
320 |
||
321 |
(*tables indexed by strings*) |
|
322 |
structure Symtab = TableFun(type key = string val ord = string_ord); |