Skip to content
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

Alternative to keysSet that uses Arg to keep the value #814

Closed
josephcsible opened this issue Jan 26, 2022 · 10 comments
Closed

Alternative to keysSet that uses Arg to keep the value #814

josephcsible opened this issue Jan 26, 2022 · 10 comments

Comments

@josephcsible
Copy link
Contributor

import qualified Data.Map.Internal as Map
import qualified Data.Set.Internal as Set
import Data.Semigroup (Arg(..))

mapToArgSet :: Map.Map k a -> Set.Set (Arg k a)
mapToArgSet Map.Tip = Set.Tip
mapToArgSet (Map.Bin sz k v l r) = Set.Bin sz (Arg k v) (mapToArgSet l) (mapToArgSet r)

This function seems safe to me, since Arg k a's Eq and Ord instances only care about k and not a. Assuming I'm right about that, would this be worth adding to Data.Map (or maybe Data.Set), as a more powerful alternative to keysSet?

@treeowl
Copy link
Contributor

treeowl commented Jan 27, 2022

It's safe enough. It could be defeated by overlapping instances, but that won't cause a memory safety problem. I really like this idea. Could you write the libraries mailing list to see if anyone has suggested improvements to the proposed API?

@treeowl
Copy link
Contributor

treeowl commented Jan 27, 2022

What about going the other way, by the way? And should we have unsafe versions that let the user provide the conversion function?

@josephcsible
Copy link
Contributor Author

josephcsible commented Jan 27, 2022

Could you write the libraries mailing list to see if anyone has suggested improvements to the proposed API?

Sure, I'll do this tonight.

What about going the other way, by the way?

You can already go the other way with the existing public API, like this: argSetToMap = mapKeysMonotonic (\(Arg k _) -> k) . fromSet (\(Arg _ v) -> v) I'm not opposed to adding this too if you still want it though.

@treeowl
Copy link
Contributor

treeowl commented Jan 27, 2022

How does that go the other way?

@josephcsible
Copy link
Contributor Author

And should we have unsafe versions that let the user provide the conversion function?

I'm not sure exactly what you mean here. What's the type of the functions you're asking for?

@josephcsible
Copy link
Contributor Author

How does that go the other way?

The thing I originally proposed has type Map.Map k a -> Set.Set (Arg k a), and the thing I said you can already do has type Set.Set (Arg k a) -> Map.Map k a.

@treeowl
Copy link
Contributor

treeowl commented Jan 27, 2022

Oh, I see now. Sleepy, so got confused. What I meant about an unsafe version was

unsafeToSet :: (k -> a -> b) -> Map k a -> Set b
unsafeToMap :: (b -> (k, a)) -> Set b -> Map k a

Probably not by those names though.

@treeowl
Copy link
Contributor

treeowl commented Jan 27, 2022

(The unsafe things could also live in an Applicative.)

@josephcsible
Copy link
Contributor Author

josephcsible commented Jan 27, 2022

Oh, I see now. Sleepy, so got confused. What I meant about an unsafe version was

unsafeToSet :: (k -> a -> b) -> Map k a -> Set b
unsafeToMap :: (b -> (k, a)) -> Set b -> Map k a

Probably not by those names though.

Sure, but note that those would also just be convenience functions that can be implemented in terms of the public API:

unsafeToSet f = mapMonotonic (\(Arg k v) -> f k v) . mapToArgSet
unsafeToMap f = argSetToMap . mapMonotonic (uncurry Arg . f)

(The unsafe things could also live in an Applicative.)

See also #816, which would let you do the same by using traverseMonotonic there instead

josephcsible added a commit to josephcsible/containers that referenced this issue Feb 2, 2022
@josephcsible
Copy link
Contributor Author

josephcsible commented Feb 2, 2022

I wrote #817 that adds my original function plus the one that goes the other way that you asked for. I'll do the unsafe versions in a separate PR.

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

No branches or pull requests

2 participants