-
Notifications
You must be signed in to change notification settings - Fork 10
Support containers-0.8
.
#18
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
3de17be
to
747201b
Compare
src/Data/IntMap/NonEmpty/Internal.hs
Outdated
-- | /O(n)/. A fixed version of 'Data.IntMap.traverseWithKey' that | ||
-- traverses items in ascending order of keys. |
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.
(Just passing by)
I know this is not from this PR, but this does not seem right. IntMap traverses in ascending order of keys, this implementation doesn't.
λ> import qualified Data.IntMap.Lazy as IM
λ> import qualified Data.IntMap.NonEmpty as NEIM
λ> () <$ IM.traverseWithKey (curry print) (IM.fromList [(i,i) | i <- [-3..2]])
(-3,-3)
(-2,-2)
(-1,-1)
(0,0)
(1,1)
(2,2)
λ> () <$ NEIM.traverseWithKey (curry print) (NEIM.unsafeFromMap (IM.fromList [(i,i) | i <- [-3..2]]))
(-3,-3)
(-1,-1)
(-2,-2)
(2,2)
(1,1)
(0,0)
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.
(Just passing by) I know this is not from this PR, but this does not seem right. IntMap traverses in ascending order of keys, this implementation doesn't.
Hi @meooow25, many thanks for commenting, I really appreciate your analysis.
Could it be that in the past, these traversal functions were not always so well-behaved?
For example, as recently as containers-0.6.2.1
, we can see a discrepancy between Data.IntMap
and Data.IntMap.Strict
in the behaviour of traverseWithKey
(borrowing your example code):
$ cabal repl --constraint=containers==0.6.2.1
> import qualified Data.IntMap as IM
> import qualified Data.IntMap.Strict as IMS
> () <$ IM.traverseWithKey (curry print) (IM.fromList [(i,i) | i <- [-3..2]])
(-3,-3)
(-2,-2)
(-1,-1)
(0,0)
(1,1)
(2,2)
> () <$ IMS.traverseWithKey (curry print) (IM.fromList [(i,i) | i <- [-3..2]])
(0,0)
(1,1)
(2,2)
(-3,-3)
(-2,-2)
(-1,-1)
But with containers-0.6.3.1
, this discrepancy is fixed:
$ cabal repl --constraint=containers==0.6.3.1
> import qualified Data.IntMap as IM
> import qualified Data.IntMap.Strict as IMS
> () <$ IM.traverseWithKey (curry print) (IM.fromList [(i,i) | i <- [-3..2]])
(-3,-3)
(-2,-2)
(-1,-1)
(0,0)
(1,1)
(2,2)
> () <$ IMS.traverseWithKey (curry print) (IM.fromList [(i,i) | i <- [-3..2]])
(-3,-3)
(-2,-2)
(-1,-1)
(0,0)
(1,1)
(2,2)
Though in any case, I think it's clear that the current implementation of traverseMapWithKey
does not work as expected. Many thanks for pointing this out! I will run some more tests and revise this PR.
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've updated this PR to remove the custom implementation of Data.IntMap.NonEmpty.Internal.traverseMapWithKey
, updating all call sites to use Data.IntMap.traverseWithKey
instead.
According to my testing, the test suite now passes for all the following versions of containers
:
0.6.3.1
0.6.4.1
0.6.5.1
0.6.6
0.6.7
0.6.8
0.7
0.8
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.
But with
containers-0.6.3.1
, this discrepancy is fixed:
Good find, the code here is likely an (incorrect) attempt to work around the containers issue.
I also think that bumping to a fixed version of containers is the best thing to do here, and one can avoid dealing with the internals 👍
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.
Thanks for reviewing -- your assement was correct, this was odd behavior in containers that was actually caught and updated by this package's property tests haskell/containers#579
This commit provides a workaround for a change in the behaviour of `Set.from{Asc,Desc}List` w.r.t. duplicate elements, when upgrading from `containers-0.7` to `containers-0.8`. We can use the `K` type from `Tests.Util` to demonstrate this. With `containers-0.7`, `Set.from{Asc,Desc}List` chooses the **_first_** occurrence of any duplicated element: ```hs $ cabal repl nonempty-containers-test --constraint=containers==0.7 > import qualified Data.Set as Set > import Tests.Util > Set.fromAscList [K 'a' 1, K 'a' 2] fromList [K {getKX = 'a', getKY = 1}] > Set.fromDescList [K 'a' 1, K 'a' 2] fromList [K {getKX = 'a', getKY = 1}] ``` With `containers-0.8`, `Set.from{Asc,Desc}List` chooses the **_last_** occurrence of any duplicated element: ```hs $ cabal repl nonempty-containers-test --constraint=containers==0.8 > import qualified Data.Set as Set > import Tests.Util > Set.fromAscList [K 'a' 1, K 'a' 2] fromList [K {getKX = 'a', getKY = 2}] > Set.fromDescList [K 'a' 1, K 'a' 2] fromList [K {getKX = 'a', getKY = 2}] ``` This commit adjusts the bias of `Data.Set.NonEmpty.combineEq` to match the bias of `Set.from{Asc,Desc}List` in the version of `containers` being linked against.
The current definition of `traverseMapWithKey` does not traverse keys in ascending order: ```hs > import qualified Data.IntMap as IM > import qualified Data.IntMap.NonEmpty.Internal as NEIM > kvs = [(i, i) | i <- [-2 .. 2]] > () <$ IM.traverseWithKey (curry print) (IM.fromList kvs) (-2,-2) (-1,-1) (0,0) (1,1) (2,2) > () <$ NEIM.traverseMapWithKey (curry print) (IM.fromList kvs) (-2,-2) (-1,-1) (2,2) (1,1) (0,0) ``` As a result, traversal functions for `Data.IntMap.NonEmpty` also do not traverse keys in ascending order. This commit redefines `traverseMapWithKey` to be a simple synonym of `Data.IntMap.traverseWithKey`. With this change, the test suite passes for all versions of containers from `0.6.3.1` up to `0.8` inclusively: - `0.6.3.1` - `0.6.4.1` - `0.6.5.1` - `0.6.6` - `0.6.7` - `0.6.8` - `0.7` - `0.8`
Since `traverseMapWithKey` is now a synonym of `IntMap.traverseWithKey`, we can inline its definition at all call sites.
94969c3
to
423cdc6
Compare
The lower bound of `0.6.3.1` is the earliest version for which all tests pass. This version of `containers` was released on 2020-07-14. This commit excludes older versions of `containers` up to and including version `0.6.2.1`, which was released on 2019-06-24.
423cdc6
to
b16f327
Compare
If the package itself is only buildable for `containers >= 0.6.3.1`, then this code is no longer reachable, and thus can be removed.
2be3cc3
to
2bb5a2a
Compare
These functions are now just synonyms, so they can be safely inlined.
2bb5a2a
to
459536f
Compare
Hi @mstksg Hope it's okay for me to have created this PR. I had some spare time over the weekend, so I took a look at how (I use If there's anything you'd like me to adjust or if you’d prefer to handle things differently, just let me know—I’d be happy to help if I can. All the best, |
Hi @mstksg Just checking in on this PR. It's been a couple of months since I opened it, so I wasn't sure if it might've been missed, or if things have just been a bit busy on your end. If there's anything you need from my side, feel free to let me know. Thanks again! |
Hi jonathan -- yes, I did miss the notification initially. Appreciate this very much, thanks for following up as well! I'll see if I can push this in this week |
This PR adds support for
containers
version0.8
.It:
Removes the custom implementation of
Data.IntMap.NonEmpty.Internal.traverseMapWithKey
and updates call sites to useData.IntMap.traverseWithKey
instead, which correctly traverses in ascending order of keys forcontainers >= 0.6.3.1
(see below.)Adjusts
Data.Set.NonEmpty.combineEq
so that:containers < 0.8
:combineEq
chooses the first occurrence of each duplicated element (consistent with behaviour ofcontainers < 0.8
).containers >= 0.8
:combineEq
chooses the last occurrence of each duplicated element (consistent with behaviour ofcontainers >= 0.8
).This is to account for a change in behaviour of
Data.Set.from{Asc,Desc}List
betweencontainers-0.7
andcontainers-0.8
:containers < 0.8
:Set.from{Asc,Desc}List
chooses the first occurrence of any duplicated element.containers >= 0.8
:Set.from{Asc,Desc}List
chooses the last occurrence of any duplicated element.Updates both lower and upper bounds for
containers
to reflect the set of versions for which all tests pass (containers >= 0.6.3.1 && < 0.9
)Removes the compatibility layer for
containers < 0.5.11
. Assuming the package is only buildable forcontainers >= 0.6.3.1
, then it should be safe to remove this layer.Testing
I have confirmed that the test suite passes for all versions of
containers
between0.6.3.1
and0.8
(inclusively):0.8
0.7
0.6.8
0.6.7
0.6.6
0.6.5.1
0.6.4.1
0.6.3.1
(released in2020-07-14
)The test suite fails for the following older versions of
containers
:0.6.2.1
(released in2019-06-24
)0.6.1.1
0.6.0.1
0.5.11.0
Tests that fail with older versions of
containers
:Tests.IntMap.mapAccumWithKey
Tests.IntMap.sequenceA
Tests.IntMap.sequence1
Tests.IntMap.traverseWithKey
Tests.IntMap.traverseWithKey1