Opened 10 years ago

Closed 9 years ago

Last modified 7 years ago

#665 closed feature request (fixed)

re-work of insert API

Reported by: jpbernardy Owned by:
Priority: normal Milestone:
Component: libraries/base Version: 6.4.1
Keywords: Data Map collections Cc:
Operating System: Unknown/Multiple Architecture: Unknown/Multiple
Type of failure: Test Case:
Blocked By: Blocking:
Related Tickets: Differential Revisions:

Description (last modified by jpbernardy)

I have been using 'Data.Map' from the library distributed with GHC/Hugs, and I quite like it. Often though, I find myself needing a function that behaves like this:

> import Data.Map (Map); import qualified Data.Map as Map hiding (Map)
>
> insert1 :: Ord k => k -> (Maybe v -> v) -> Map k v -> (v, Map k v)
> insert1 k f m   = let v = f (Map.lookup k m)
>                   in (v, Map.insert k v m)

In words, we use a function to determine what to place in the map, depending on what is already in the map. In the result, we return the new map, and the value that was inserted in the map. Here is an example of how we may use this function:

> example m           = insert1 0 v m
>   where v Nothing   = 0
>         v (Just n)  = n + 1

Clearly, I can implement this function myself as above. However, I was wondering if I can achieve the same, without searching in the map twice. I came up with the following:

> insert2 :: Ord k => k -> (Maybe v -> v) -> Map k v -> (v, Map k v)
> insert2 k f m   = (v,m')
>   where
>   v             = f r
>   (r, m')       = Map.insertLookupWithKey g k v m
>   g _ x _       = x

Is there a more direct way to implement this function? The use of lazyness in this case seems like an overkill. If not, I would like to suggest that we add it to the API. Also, it seems that some of the functions in the library are quite easy to implement in terms of this function, so perhaps they don't need to be in the API?

> insertWith' :: Ord k => (v -> v -> v) -> k -> v -> Map k v -> Map k v
> insertWith' f k v m = snd (insert2 k (maybe v (f v)) m)
>
> insertWithKey' :: Ord k => (k -> v -> v -> v) -> k -> v -> Map k v -> Map k v
> insertWithKey' f k v m = snd (insert2 k (maybe v (f k v)) m)

Change History (6)

comment:1 Changed 10 years ago by jpbernardy

  • Keywords collections added

comment:2 Changed 10 years ago by jpbernardy

  • Description modified (diff)

comment:3 Changed 9 years ago by jpbernardy

I've decided to provide the more general update function

    update :: (Maybe a -> Maybe a) -> k -> c -> c

comment:4 Changed 9 years ago by jpbernardy

  • Resolution set to fixed
  • Status changed from new to closed

comment:5 Changed 7 years ago by simonmar

  • Architecture changed from Unknown to Unknown/Multiple

comment:6 Changed 7 years ago by simonmar

  • Operating System changed from Unknown to Unknown/Multiple
Note: See TracTickets for help on using tickets.