Open sergv opened 8 years ago
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.
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.
Thanks for alterF, that's exactly what I needed :+1:
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.
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?
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
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.