<html><head><meta http-equiv="Content-Type" content="text/html charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; -webkit-line-break: after-white-space; ">There is a list of problems with the current "Map" and "IntMap" modification interfaces:<br><br> - they are filled with quirky and too specialized functions<br><br> - they are not consistent in terms of how equally named functions behave: <a href="http://hackage.haskell.org/packages/archive/containers/latest/doc/html/Data-IntMap-Strict.html#v:updateLookupWithKey">http://hackage.haskell.org/packages/archive/containers/latest/doc/html/Data-IntMap-Strict.html#v:updateLookupWithKey</a><br><br> - they still don't cover some important scenarios of use<br><br>Because of the above I have very often found myself in requirement for the following function:<br><br> withItem ::<br> (Ord k) =><br> k -><br> (Maybe i -> (r, Maybe i)) -><br> Map k i -> (r, Map k i)<br> withItem k f m = <br> let<br> item = Map.lookup k m<br> (r, item') = f item<br> m' = Map.update (const item') k m<br> in (r, m')<br><br>It covers all the imaginable scenarios of modification operations: delete, update, replace, - yet it also provides one with ability to extract the modified data and not only. The problem is that this implementation involves a repeated lookup for the same item: first with "lookup", then with "update" - but the "containers" library exposes no functionality to get around that. So I suggest to implement an efficient version of "withItem" in the library.<br><br>This function turns out to be far more generalized than any of the currently present in the library, so it can become a basic building block for all sorts of modifying functions, including all the already existing ones, e.g.:<br><br> alter :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a<br> alter f k = snd . withItem k (\i -> ((), f i))<br><br> delete :: Ord k => k -> Map k a -> Map k a<br> delete k = snd . withItem k (const ((), Nothing))<br><br> updateLookupWithKey :: <br> (Ord k) => <br> (k -> a -> Maybe a) -> <br> k -> <br> Map k a -> (Maybe a, Map k a)<br> updateLookupWithKey f k = <br> withItem k $ \i -> case i of<br> Just i -> case f k i of<br> Nothing -> (Just i, Nothing)<br> Just i' -> (Just i', Just i')<br> _ -> (Nothing, Nothing)<br><br>You can see how easy it makes to achieve any sort of specialized functionality. So, besides the evident benefits, this function can also become a replacement for a whole list of confusing specialized ones, thus greatly lightening the library.<br><br>You might have also noticed how this function is based around the standard "a -> (b, a)" pattern of the "State" monad, thus making it easily composable with it using the "state" and "runState" functions.<br><br>Summarizing, my suggestions are:<br><br> 1. Implement an efficient version of "withItem" for lazy and strict versions of "Map" and "IntMap".<br><br> 2. Change the order of parameters from "lambda -> key" to "key -> lambda". The "updateLookupWithKey" example implementation shows how this change can be benefitial.<br><br> 3. Begin the deprecation process of the following functions: insertWith, insertWithKey, insertLookupWithKey, adjust, adjustWithKey, update, updateWithKey, updateLookupWithKey, alter.<br><br>A deadline for discussion is set to 6 weeks.<br><br>For a formatted version of this message please visit <a href="https://github.com/haskell/containers/issues/28">https://github.com/haskell/containers/issues/28</a>.<br></body></html>