@@ -8,6 +8,30 @@ module Dict (empty,singleton,insert
8 ,toList,fromList
8 ,toList,fromList
11+{-|A dictionary mapping unique keys to values. The keys can be any comparable
12+type. This includes `Int`, `Float`, `Time`, `Char`, `String`, and tuples or
13+lists of comparable types.
15+Insert, remove, and query operations all take *O(log n)* time.
18+@docs empty, singleton, insert, remove
21+@docs member, lookup, findWithDefault
24+@docs union, intersect, diff
27+@docs keys, values, toList, fromList
30+@docs map, foldl, foldr
11import open Basics
35import open Basics
12import open Maybe
36import open Maybe
13import Native.Error
37import Native.Error
@@ -18,7 +42,7 @@ data NColor = Red | Black
19data Dict k v = RBNode NColor k v (Dict k v) (Dict k v) | RBEmpty
43data Dict k v = RBNode NColor k v (Dict k v) (Dict k v) | RBEmpty
21−-- Create an empty dictionary.
45+{-| Create an empty dictionary. -}
22empty : Dict comparable v
46empty : Dict comparable v
23empty = RBEmpty
47empty = RBEmpty
@@ -116,7 +140,7 @@ max t =
119−-- Lookup the value associated with a key.
143+{-| Lookup the value associated with a key. -}
120lookup : comparable -> Dict comparable v -> Maybe v
144lookup : comparable -> Dict comparable v -> Maybe v
121lookup k t =
145lookup k t =
122 case t of
146 case t of
@@ -127,8 +151,8 @@ lookup k t =
127 EQ -> Just v
151 EQ -> Just v
128 GT -> lookup k r
152 GT -> lookup k r
130−-- Find the value associated with a key. If the key is not found,
154+{-| Find the value associated with a key. If the key is not found,
131−-- return the default value.
155+return the default value. -}
132findWithDefault : v -> comparable -> Dict comparable v -> v
156findWithDefault : v -> comparable -> Dict comparable v -> v
133findWithDefault base k t =
157findWithDefault base k t =
134 case t of
158 case t of
@@ -152,7 +176,7 @@ find k t =
155−-- Determine if a key is in a dictionary.
179+{-| Determine if a key is in a dictionary. -}
156member : comparable -> Dict comparable v -> Bool
180member : comparable -> Dict comparable v -> Bool
157-- Does t contain k?
181-- Does t contain k?
158member k t = isJust <| lookup k t
182member k t = isJust <| lookup k t
@@ -208,8 +232,8 @@ ensureBlackRoot t =
208 RBNode Red k v l r -> RBNode Black k v l r
232 RBNode Red k v l r -> RBNode Black k v l r
211−-- Insert a key-value pair into a dictionary. Replaces value when there is
235+{-| Insert a key-value pair into a dictionary. Replaces value when there is
212−-- a collision.
236+a collision. -}
213insert : comparable -> v -> Dict comparable v -> Dict comparable v
237insert : comparable -> v -> Dict comparable v -> Dict comparable v
214insert k v t = -- Invariant: t is a valid left-leaning rb tree
238insert k v t = -- Invariant: t is a valid left-leaning rb tree
215 let ins t =
239 let ins t =
@@ -231,7 +255,7 @@ insert k v t = -- Invariant: t is a valid left-leaning rb tree
231 else new_t)
255 else new_t)
234−-- Create a dictionary with one key-value pair.
258+{-| Create a dictionary with one key-value pair. -}
235singleton : comparable -> v -> Dict comparable v
259singleton : comparable -> v -> Dict comparable v
236singleton k v = insert k v RBEmpty
260singleton k v = insert k v RBEmpty
@@ -312,8 +336,8 @@ deleteMax t =
312 in ensureBlackRoot (del t)
336 in ensureBlackRoot (del t)
315−-- Remove a key-value pair from a dictionary. If the key is not found,
339+{-| Remove a key-value pair from a dictionary. If the key is not found,
316−-- no changes are made.
340+no changes are made. -}
317remove : comparable -> Dict comparable v -> Dict comparable v
341remove : comparable -> Dict comparable v -> Dict comparable v
318remove k t =
342remove k t =
319 let eq_and_noRightNode t =
343 let eq_and_noRightNode t =
@@ -346,58 +370,58 @@ remove k t =
346 Native.Error.raise "invariants broken after remove")
370 Native.Error.raise "invariants broken after remove")
349−-- Apply a function to all values in a dictionary.
373+{-| Apply a function to all values in a dictionary. -}
350map : (a -> b) -> Dict comparable a -> Dict comparable b
374map : (a -> b) -> Dict comparable a -> Dict comparable b
352 case t of
376 case t of
353 RBEmpty -> RBEmpty
377 RBEmpty -> RBEmpty
354 RBNode c k v l r -> RBNode c k (f v) (map f l) (map f r)
378 RBNode c k v l r -> RBNode c k (f v) (map f l) (map f r)
356−-- Fold over the key-value pairs in a dictionary, in order from lowest
380+{-| Fold over the key-value pairs in a dictionary, in order from lowest
357−-- key to highest key.
381+key to highest key. -}
358foldl : (comparable -> v -> b -> b) -> b -> Dict comparable v -> b
382foldl : (comparable -> v -> b -> b) -> b -> Dict comparable v -> b
359foldl f acc t =
383foldl f acc t =
360 case t of
384 case t of
361 RBEmpty -> acc
385 RBEmpty -> acc
362 RBNode _ k v l r -> foldl f (f k v (foldl f acc l)) r
386 RBNode _ k v l r -> foldl f (f k v (foldl f acc l)) r
364−-- Fold over the key-value pairs in a dictionary, in order from highest
388+{-| Fold over the key-value pairs in a dictionary, in order from highest
365−-- key to lowest key.
389+key to lowest key. -}
366foldr : (comparable -> v -> b -> b) -> b -> Dict comparable v -> b
390foldr : (comparable -> v -> b -> b) -> b -> Dict comparable v -> b
367foldr f acc t =
391foldr f acc t =
368 case t of
392 case t of
369 RBEmpty -> acc
393 RBEmpty -> acc
370 RBNode _ k v l r -> foldr f (f k v (foldr f acc r)) l
394 RBNode _ k v l r -> foldr f (f k v (foldr f acc r)) l
372−-- Combine two dictionaries. If there is a collision, preference is given
396+{-| Combine two dictionaries. If there is a collision, preference is given
373−-- to the first dictionary.
397+to the first dictionary. -}
374union : Dict comparable v -> Dict comparable v -> Dict comparable v
398union : Dict comparable v -> Dict comparable v -> Dict comparable v
375union t1 t2 = foldl insert t2 t1
399union t1 t2 = foldl insert t2 t1
377−-- Keep a key-value pair when its key appears in the second dictionary.
401+{-| Keep a key-value pair when its key appears in the second dictionary.
378−-- Preference is given to values in the first dictionary.
402+Preference is given to values in the first dictionary. -}
379intersect : Dict comparable v -> Dict comparable v -> Dict comparable v
403intersect : Dict comparable v -> Dict comparable v -> Dict comparable v
380intersect t1 t2 =
404intersect t1 t2 =
381 let combine k v t = if k `member` t2 then insert k v t else t
405 let combine k v t = if k `member` t2 then insert k v t else t
382 in foldl combine empty t1
406 in foldl combine empty t1
384−-- Keep a key-value pair when its key does not appear in the second dictionary.
408+{-| Keep a key-value pair when its key does not appear in the second dictionary.
385−-- Preference is given to the first dictionary.
409+Preference is given to the first dictionary. -}
386diff : Dict comparable v -> Dict comparable v -> Dict comparable v
410diff : Dict comparable v -> Dict comparable v -> Dict comparable v
387diff t1 t2 = foldl (\k v t -> remove k t) t1 t2
411diff t1 t2 = foldl (\k v t -> remove k t) t1 t2
389−-- Get all of the keys in a dictionary.
413+{-| Get all of the keys in a dictionary. -}
390keys : Dict comparable v -> [comparable]
414keys : Dict comparable v -> [comparable]
391keys t = foldr (\k v acc -> k :: acc) [] t
415keys t = foldr (\k v acc -> k :: acc) [] t
393−-- Get all of the values in a dictionary.
417+{-| Get all of the values in a dictionary. -}
394values : Dict comparable v -> [v]
418values : Dict comparable v -> [v]
395values t = foldr (\k v acc -> v :: acc) [] t
419values t = foldr (\k v acc -> v :: acc) [] t
397−-- Convert a dictionary into an association list of key-value pairs.
421+{-| Convert a dictionary into an association list of key-value pairs. -}
398toList : Dict comparable v -> [(comparable,v)]
422toList : Dict comparable v -> [(comparable,v)]
399toList t = foldr (\k v acc -> (k,v) :: acc) [] t
423toList t = foldr (\k v acc -> (k,v) :: acc) [] t
401−-- Convert an association list into a dictionary.
425+{-| Convert an association list into a dictionary. -}
402fromList : [(comparable,v)] -> Dict comparable v
426fromList : [(comparable,v)] -> Dict comparable v
403fromList assocs = List.foldl (\(k,v) d -> insert k v d) empty assocs
427fromList assocs = List.foldl (\(k,v) d -> insert k v d) empty assocs