Skip to content

Consider adding applicative/monadic versions of adjust/update/alter functions #278

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
sergv opened this issue May 31, 2016 · 6 comments
Open

Comments

@sergv
Copy link

sergv commented May 31, 2016

These three functions are pure, which is really great. But I believe purity gets it the way in the following use case: add key-value pair if key is not present or throw error in a monad if key is already present.

Sharing traversal for both presence check and update will avoid redundant work.

@treeowl
Copy link
Contributor

treeowl commented May 31, 2016

I've added alterF to Data.Map (with a seriously over-engineered implementation). I copied the at code from Control.Lens.At to offer the same in Data.IntMap, where it's really not worth trying to be clever except possibly to add a rewrite rule for Identity. I'm open to offering adjustA as well, which could reuse code from alterF for Data.Map and steal ix code from Control.Lens.At for Data.IntMap and Data.Sequence. You should send a proposal to the libraries list. I'm not convinced updateA would get much use, but you're welcome to bring it up on the list if you like.

@treeowl
Copy link
Contributor

treeowl commented May 31, 2016

I just realized we can include Data.Set and Data.IntSet in this game if we want. lens takes them to Maybe (), which is good for lens consistency, but we'd want to use Bool instead.

@sergv
Copy link
Author

sergv commented Jun 6, 2016

Thanks for alterF, that's exactly what I needed 👍

@mitchellwrosen
Copy link

Neat, I think alterF subsumes some work I've done over the past day or so on integrating focus with containers: https://github.com/mitchellwrosen/containers-focus

The main motivator was deleting an element and looking it up at the same time:

deleteLookup :: Ord k => k -> Map k a -> (Maybe a, Map k a)
deleteLookup = focus (, Remove)

alterF can do it too with the (x ,) functor:

deleteLookup :: Ord k => k -> Map k a -> (Maybe a, Map k a)
deleteLookup = alterF (, Nothing)

However, I wouldn't exactly say this is obvious, especially to a newer Haskeller. Perhaps the documentation could be improved around this function.

@treeowl
Copy link
Contributor

treeowl commented Nov 12, 2016

I'm always open to documentation suggestions and pull requests, and I think it does make sense to add an explanation of how to use alterF with the rather important (,) x functor. That said, I don't want to copy a lens tutorial into containers. I'd much rather link to lens documentation somewhere else, either to lens specifically, to some less ambitious library, or perhaps to a general tutorial. Do you have suggestions for link targets?

@mitchellwrosen
Copy link

mitchellwrosen commented Nov 14, 2016

I don't think a lens tutorial is necessary, as alterF isn't quite compatible out-of-the-box with lenses anyway. How about just a bunch of example uses for the function that can't be implemented any other way?

Identity and Const are bad examples - these just give you alter and lookup.

Deleting a value and looking it up at the same time:

deleteLookup :: Ord k => k -> Map k a -> (Maybe a, Map k a)
deleteLookup = alterF (, Nothing)

Deleting a value and returning whether or not it was deleted:

deleteSuccess :: Ord k => k -> Map k a -> (Bool, Map k a)
deleteSuccess = alterF (\x -> (isJust x, Nothing))

Inserting a value and return what was overwritten:

overwrite :: Ord k => k -> a -> Map k a -> (Maybe a, Map k a)
overwrite k a = alterF (, Just a)

... yeah these are all the (,) functor. Can't think of any other examples =P

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