-
Notifications
You must be signed in to change notification settings - Fork 101
Add 'fromListWithKey' to HashMap #246
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
Conversation
Can we reuse the unsafe function you wrote for |
Yes, I suppose we could do that. I haven't looked in to the performance implications yet though. Will do. |
Btw, the travis failure seems unrelated to my change. |
Ok, so I've benchmarked the effect of having both full implementations for The numbers change quite a bit, even for unrelated benchmarks. I assume that's due to code layout effects. If anything, the trend seems to be that it's slightly better define |
See haskell-unordered-containers#246 (comment) for performance numbers.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Summary: Test Plan: Reviewers: Subscribers: Tasks: Tags:
See haskell-unordered-containers#246 (comment) for performance numbers.
Thanks to @emilypi for the suggestions
It models the test for fromListWith but makes sure that values are combined in a way that depends on the key.
I've added some more documentation and tests. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, @josefs! :)
I have a few more comments, but I think we're on a good track.
Data/HashMap/Base.hs
Outdated
-- > combine Mul = (*) | ||
-- > combine Add = (+) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Commutative operations make it harder to infer the behaviour of the function from the example.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Really? I thought that they would make it easier! The example is supposed to use the difference between addition and multiplication as a way to let the key affect combining the keys.
What would you suggest I use instead?
I suppose I could use something like taking the first or the last element, depending on the key.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe something like
combine k x y = [ k ] ++ x ++ y
?
With a commutative operation you can't tell in which order the elements are being inserted which is an important gotcha here.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not a big fan of combining the key with the values in the way you suggest. That's how it's documented in Data.Map and I specifically tried to avoid it because I think it seems very contrived.
The point about the order of operations is made in the last lines of the documentation. This mirrors the documentation of fromListWith
which also has examples which uses commutative operators but then explains below the order of operations. I kind of like that structure.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmm, the thing is that IMHO fromListWith
and fromListWithKey
really have this rather serious design mistake where
fromListWith op [(k, a), (k, b)]
is not the obvious
fromList [(k, op a b)]
but instead
fromList [(k, op b a)]
I wish we could fix this properly but that's not a task for this PR.
So IMHO we need to ensure that potential users of fromListWith[Key]
become aware of this gotcha ASAP so they do not produce a bug, for which I feel we, as the library authors and maintainers, would share some responsibility!
Currently the only way these haddocks hint at the gotcha is in the last two lines, which IMHO are fairly abstract and easy to overlook TLDR-style.
I think the documentation for fromListWith
is less problematic because the first example with the commutative operation is very short, and the next example is very clear about the issue.
So maybe consider using David's free magma suggestion (which I feel is slightly abstract) or maybe just use Sub
and Div
instead of Add
and Mul
…
The old properties used associative operators to combine values when there were duplicate keys. With this diff we're using a non-commutative and non-associative operator which can catch more bugs.
This got lost in a rebase
Free magmas are great for arbitrary operations. data Magma a
= Leaf a
| Op (Magma a) (Magma a) If you pull up an arbitrary |
Oh, I got mixed up. Thought you were talking about testing rather than
documentation. The ergonomics are indeed quite awful. It would be much
clearer if we had something like
flwk
:: (Hashable k, Eq k)
=> (k -> Maybe b -> a -> Box b) -> [(k,a)] -> HashMap k b
(where data Box a = Box a)
or even
flwkm
:: (Hashable k, Eq k)
=> (k -> Maybe b -> a -> Maybe b) -> [(k,a)] -> HashMap k b
…On Tue, Jun 2, 2020, 4:31 PM Simon Jakobi ***@***.***> wrote:
***@***.**** commented on this pull request.
------------------------------
In Data/HashMap/Base.hs
<#246 (comment)>
:
> +-- > combine Mul = (*)
+-- > combine Add = (+)
Hmm, the thing is that IMHO fromListWith and fromListWithKey really have
this rather serious design mistake where
fromListWith op [(k, a), (k, b)]
is not the obvious
fromList [(k, op a b)]
but instead
fromList [(k, op b a)]
I wish we could fix this properly but that's not a task for this PR.
So IMHO we need to ensure that potential users of fromListWith[Key]
become aware of this gotcha ASAP so they *do not* produce a bug, for
which I feel we, as the library authors and maintainers, would share some
responsibility!
Currently the only way these haddocks *hint* at the gotcha is in the last
two lines, which IMHO are fairly abstract and easy to overlook TLDR-style.
I think the documentation for fromListWith is less problematic because
the first example with the commutative operation is very short, and the
next example is very clear about the issue.
So maybe consider using David's free magma suggestion (which I feel is
*slightly* abstract) or maybe just use Sub and Div instead of Add and Mul…
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#246 (comment)>,
or unsubscribe
<https://github.com/notifications/unsubscribe-auth/AAOOF7NWYF25GCDRVCZA6UDRUVOSTANCNFSM4KIKMSJQ>
.
|
…ciative operators Since the combining function is applied in a way that can be counter-intuitive it's more pedagical to to use operators which better illustrate this behaviour.
@sjakobi I've updated the documentation to use division and subtraction instead to better illustrate the non-obvious way in which values are combined. I really liked the free magma suggestion from @treeowl so I've converted the tests to use that. I believe that should take care of all the outstanding issues for this PR so it should be good to go for the next release. Btw, it might be good to squash at least some of these commits. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thank you, @josefs! :)
No description provided.