Skip to content

Add upsert #809

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
phadej opened this issue Jan 9, 2022 · 3 comments
Open

Add upsert #809

phadej opened this issue Jan 9, 2022 · 3 comments

Comments

@phadej
Copy link
Contributor

phadej commented Jan 9, 2022

There are

adjust :: Ord k => (      a ->       a) -> k -> Map k a -> Map k a
update :: Ord k => (      a -> Maybe a) -> k -> Map k a -> Map k a
alter  :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a

but

upsert :: Ord k => (Maybe a ->       a) -> k -> Map k a -> Map k a

variant is missing.

While it's definable with upsert f = alter (Just . f), I'd like to have it already in the library.

Compare implementation for Map:
even alter is tagged as INLINEABLE, the optimization may or may not happen.

alter :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a
alter = go
  where
    go :: Ord k => (Maybe a -> Maybe a) -> k -> Map k a -> Map k a
    go f !k Tip = case f Nothing of
               Nothing -> Tip
               Just x  -> singleton k x

    go f k (Bin sx kx x l r) = case compare k kx of
               LT -> balance kx x (go f k l) r
               GT -> balance kx x l (go f k r)
               EQ -> case f (Just x) of
                       Just x' -> Bin sx kx x' l r
                       Nothing -> glue l r

vs

upsert :: Ord k => (Maybe a -> a) -> k -> Map k a -> Map k a
upsert = go
  where
    go :: Ord k => (Maybe a -> a) -> k -> Map k a -> Map k a
    go f !k Tip = singleton k (f Nothing)
    go f k (Bin sx kx x l r) = case compare k kx of
               LT -> balance kx x (go f k l) r
               GT -> balance kx x l (go f k r)
               EQ -> Bin sx kx (f (Just x)) l r

In fact, I'd like having upsertF variant as well.
It would be less code/branches then with alterF.

@treeowl
Copy link
Contributor

treeowl commented Jan 9, 2022

It sounds reasonable.

@Bodigrim
Copy link
Contributor

Bodigrim commented Mar 8, 2024

+1, I've just spent some time trying to locate Ord k => (Maybe a -> a) -> k -> Map k a -> Map k a, only to realise that it's missing indeed.

@meooow25
Copy link
Contributor

+1 to adding this.
Does this function exist in other libraries? It would be good to be consistent on the name if so.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants