Skip to content

Function for updating with default value (mostly for nested maps) #888

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

Closed
Lev135 opened this issue Dec 28, 2022 · 2 comments
Closed

Function for updating with default value (mostly for nested maps) #888

Lev135 opened this issue Dec 28, 2022 · 2 comments

Comments

@Lev135
Copy link

Lev135 commented Dec 28, 2022

Maybe, I'm doing something wrong, but this combination is very frequent in my programms. Imagine we have some nested map

m :: Map Foo (Map Bar Baz)

and we want to insert a value baz to the bar of foo. I think it would be nice to have something like

mupdate :: Monoid a => (a -> a) -> k -> Map k a -> Map k a
mupdate upd = alter (Just . upd . fromMaybe mempty)

to call this like mupdate (insert bar baz) foo.
Maybe with upsert from #809 it will be also acceptable --- just upsert (insert bar baz . fromMaybe mempty) foo or even there is a perfect way using currently implemented functionality, but I can't see them.

P. S. of course, this can be easily done throw non from lens, but lens are not always advisable

@alexfmpe
Copy link
Contributor

alexfmpe commented Jan 10, 2023

Maybe you want insertWith union foo (singleton bar baz)?

> f a b c = insertWith union a (singleton b c)

> :t f
f :: (Ord k1, Ord k2) => k1 -> k2 -> a -> Map k1 (Map k2 a) -> Map k1 (Map k2 a)

> f "0" "1" "2" mempty
fromList [("0",fromList [("1","2")])]

> f "0" "1" "2" $ singleton "0" mempty
fromList [("0",fromList [("1","2")])]

> f "0" "1" "2" $ singleton "0" $ singleton "1" ""
fromList [("0",fromList [("1","2")])]

Alternatively, see https://hackage.haskell.org/package/monoidal-containers. That should let you do nested inserts direcly

let path = singleton a $ singleton b $ singleton c $ First d
in path <> oldMap

@meooow25
Copy link
Contributor

Your situation is reasonable, but

mupdate :: Monoid a => (a -> a) -> k -> Map k a -> Map k a
mupdate upd = alter (Just . upd . fromMaybe mempty)

I don't think this is a good idea, because this is not about a monoid, only about some form of default value.

A monoidal map better integrates with monoid values, and might be a better fit for your data as alexfmpe says above.

If not, you've already found that can use alter, insertWith, or upsert when it's added, to define your function.

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

3 participants