on master help sign in
Merge pull request #3868 from Synthetica9/SortedMapMerge

SortedMap merge

commit8897f649b6aadd00f01651ac4e2dc08b6bbb7c6d authorNiklas Larsson <metaniklas@gmail.com> dateMon 19 Jun 2017, 13:08 (9 years ago) parentc0463b7394567b
2 files changed+56−1
libs/contrib/Data/SortedMap.idr+52−1 libs/contrib/Data/SortedSet.idr+4
libs/contrib/Data/SortedMap.idr+52−1
@@ -1,6 +1,6 @@
11module Data.SortedMap
22
3−-- TODO: write merge and split
3+-- TODO: write split
44
55private
66data Tree : Nat -> (k : Type) -> Type -> Ord k -> Type where
@@ -214,6 +214,10 @@ insert k v (M _ t) =
214214 Left t' => (M _ t')
215215 Right t' => (M _ t')
216216
217+export
218+insertFrom : Foldable f => f (k, v) -> SortedMap k v -> SortedMap k v
219+insertFrom = flip $ foldl $ flip $ uncurry insert
220+
217221export
218222delete : k -> SortedMap k v -> SortedMap k v
219223delete _ Empty = Empty
@@ -235,6 +239,16 @@ toList : SortedMap k v -> List (k, v)
235239toList Empty = []
236240toList (M _ t) = treeToList t
237241
242+||| Gets the keys of the map.
243+export
244+keys : SortedMap k v -> List k
245+keys = map fst . toList
246+
247+||| Gets the values of the map. Could contain duplicates.
248+export
249+values : SortedMap k v -> List v
250+values = map snd . toList
251+
238252treeMap : (a -> b) -> Tree n k a o -> Tree n k b o
239253treeMap f (Leaf k v) = Leaf k (f v)
240254treeMap f (Branch2 t1 k t2) = Branch2 (treeMap f t1) k (treeMap f t2)
@@ -245,3 +259,40 @@ export
245259implementation Functor (SortedMap k) where
246260 map _ Empty = Empty
247261 map f (M n t) = M _ (treeMap f t)
262+
263+||| Merge two maps. When encountering duplicate keys, using a function to combine the values.
264+||| Uses the ordering of the first map given.
265+export
266+mergeWith : (v -> v -> v) -> SortedMap k v -> SortedMap k v -> SortedMap k v
267+mergeWith f x y = insertFrom inserted x where
268+ inserted : List (k, v)
269+ inserted = do
270+ (k, v) <- toList y
271+ let v' = (maybe id f $ lookup k x) v
272+ pure (k, v')
273+
274+||| Merge two maps using the Semigroup (and by extension, Monoid) operation.
275+||| Uses mergeWith internally, so the ordering of the left map is kept.
276+export
277+merge : Semigroup v => SortedMap k v -> SortedMap k v -> SortedMap k v
278+merge = mergeWith (<+>)
279+
280+||| Left-biased merge, also keeps the ordering specified by the left map.
281+export
282+mergeLeft : SortedMap k v -> SortedMap k v -> SortedMap k v
283+mergeLeft = mergeWith const
284+
285+-- TODO: is this the right variant of merge to use for this? I think it is, but
286+-- I could also see the advantages of using `mergeLeft`. The current approach is
287+-- strictly more powerful I believe, because `mergeLeft` can be emulated with
288+-- the `First` monoid. However, this does require more code to do the same
289+-- thing.
290+export
291+Semigroup v => Semigroup (SortedMap k v) where
292+ (<+>) = merge
293+
294+||| For `neutral <+> y`, y is rebuilt in `Ord k`, so this is not a "strict" Monoid.
295+||| However, semantically, it should be equal.
296+export
297+(Ord k, Semigroup v) => Monoid (SortedMap k v) where
298+ neutral = empty
libs/contrib/Data/SortedSet.idr+4
@@ -60,3 +60,7 @@ Ord k => Semigroup (SortedSet k) where
6060export
6161Ord k => Monoid (SortedSet k) where
6262 neutral = empty
63+
64+export
65+keySet : SortedMap k v -> SortedSet k
66+keySet = SetWrapper . map (const ())