Description
I propose adding
pop :: Ord k => k -> Map k a -> Maybe (a, Map k a)
pop :: Ord a => a -> Set a -> Maybe (Set a)
pop :: Int -> IntMap a -> Maybe (a, IntMap a)
pop :: Int -> IntSet -> Maybe IntSet
Returns a Nothing
if the key is absent. Otherwise, returns a new set or map with the key removed, and the value in case it is a map.
Previously proposed in #757 (with Maybe
on the inside). I agree with the reasons there.
- They're useful functions I expected to be in
Data.Map
andData.IntMap
. (This might be influenced by the fact that they're defined on Python'sdict
.)- Their implementations (~
updateLookupWithKey (\_ _ -> Nothing)
) is harder to parse than a simplepop
, which should help Haskell codebases become a bit cleaner :).- Their implementations are a bit non-obvious. My first instinct was to write
(Map.lookup ..., Map.delete ...)
, which would have done two traversals. Having "properly" implemented functions in the lib would prevent people from writing their own suboptimal ones.
Some more reasons:
k -> Map k a -> Maybe (a, Map k a)
is a closer inverse ofinsert
thandelete
.updateLookupWithKey (\_ _ -> Nothing)
is inefficient because 1. it takes a function which is unnecessary and 2. it always constructs a new map/set.
Previously, there were some concerns about whether this is a user-demanded feature on the libraries thread (e.g. here), and the answer is yes! Hackage Search reveals quite a few results: https://hackage-search.serokell.io/?q=%5C.updateLookupWithKey%5Cs. Some examples:
I expect there are more instances doing lookup
+delete
, and it's harder to search for those.
Naming
Some suggestions were:
pop
- seems fine to meextract
- doesn't make much sense for setslookupDelete
- long name, also doesn't make much sense for sets. Sets would needmemberDelete
.
Implementation
There are two ways to implement this.
- Simple: Go down the map/set and back up constructing the new result if the key was removed.
- Complicated: Find the path to the key in one pass down,
alterF
style, then delete only if the key was present.
"Simple" should be faster in case the key is present, "Complicated" should be faster in case the key is absent. I think the simple way should be fine. Either way, unlike updateLookupWithKey
, we don't construct a map/set if the key is absent.