-
Notifications
You must be signed in to change notification settings - Fork 186
Description
Consider inserting (k, v) elements into a map (Data.Map) in a
scenario where if the element exists you want to combine the new
element (v) with the old existing element. For this we have function:
insertWith :: Ord k => (a -> a -> a) -> k -> a -> Map k a -> Map k a
which does the trick.
But consider this scenario:
m : Map Key [Values]
and when we insert we want to add another value to the list if the key
is there.
We now have to do:
insertWith (++) k [newV] m
So we need to build a new singleton list and then call append from
every insert. The suggestion is to add a new function in which we
parametrize more generally over the value of the map as below.
insertWith' :: Ord k => (a -> m a -> m a) -> (a -> m a) -> k -> a
-> M.Map k (m a) -> M.Map k (m a)
The behavior we want is the following but without the double tree
traversal (2*log(n)) cost.
insertWith' f g k a m
= M.insert
k
(case M.lookup k m of
Nothing -> g a
Just ma -> f a ma)
m
With such a function for the example above we could then do:
insertWith' (:) (: []) k a m
and so avoid creating the singleton lists. Of course this is not specific to lists... it would help with any container value in the position of map value.