Hlint: suggest nub alternative#11825
Conversation
- Add growth rate note
| | n <- | ||
| nub $ | ||
| ordNub $ | ||
| sort $ |
There was a problem hiding this comment.
I guess the sort no longer needed
There was a problem hiding this comment.
Not quite: ordNub does not change the order of elements, so it's not semantically equivalent to drop sort. (I don't know whether sorting makes any difference for the purposes of this function and elsewhere, but perhaps we can leave figuring this out for another time)
|
|
||
| uniqueNames :: Bool | ||
| uniqueNames = length allExplanationIdStrings == length (nub allExplanationIdStrings) | ||
| uniqueNames = length allExplanationIdStrings == length (ordNub allExplanationIdStrings) |
There was a problem hiding this comment.
Not a regression, but this is wasteful. Would be nice to have a helper areUnique :: Ord a => [a] -> Bool, there is at least one more use case for it above.
There was a problem hiding this comment.
Can you please be more specific?
-- Like `uniqueNames` in the way it is implemented but taking a `[a]`.
areUnique :: Ord a => [a] -> Bool
areUnique xs = length xs == length (ordNub xs)I went looking in this repository for other [a] -> Bool helper functions and there are a few, including these ones with the same signature:
cabal/Cabal-tests/tests/UnitTests/Distribution/Compat/Graph.hs
Lines 64 to 71 in e7aaad8
cabal/cabal-install/tests/UnitTests/Distribution/Client/UserConfig.hs
Lines 93 to 96 in e7aaad8
There was a problem hiding this comment.
I also found these two doing the same thing, the opposite of all items being unique, all items being duplicates:
cabal/solver-benchmarks/HackageBenchmark.hs
Lines 351 to 352 in e7aaad8
cabal/cabal-install-solver/src/Distribution/Solver/Modular/Linking.hs
Lines 518 to 521 in e7aaad8
Other implementations found hoogling:
allEqual :: Eq a => [a] -> Bool
allEqual [] = True
allEqual (x : xs) = all (== x) xsallSame :: Eq a => [a] -> Bool
allSame [] = True
allSame (x:xs) = all (x ==) xsThere was a problem hiding this comment.
I mean that areUnique xs = length xs == length (ordNub xs) is a very expensive implementation. It is better than the one using nub, but still not great. You would expect such function to return False as soon as it meets the first non-unique element, but the implementation has to build ordNub xs in full until being able to compare lengths.
It should be something like
isUnique :: [a] -> Bool
isUnique = go S.empty
where
go !_ [] = True
go seen (x : xs) = if S.member x seen then False else go (S.insert x seen) xsallEqual expressed via nub also has bad performance, it should be like Agda's implementation.
Up to you whether you want to fix these things in this PR, it's indeed a bit of scope creep.
| | -- | A specific file within a specific component. | ||
| BuildTargetFile ComponentName FilePath | ||
| deriving (Eq, Show, Generic) | ||
| deriving (Eq, Ord, Show, Generic) |
There was a problem hiding this comment.
Ideally this deserves @since. Same below.
Fixes #11824.
When fired, this suggestion renders as:
I didn't correct
O(n log n)to theO(n log d)from containers haddocks fornubOrd. Neither did I suggest using that equivalent function from containers. For that, I raised #11826.I had to add
Ordinstances to a few data types,BuildTargetandMatchError. I changed theEqconstraint to anOrdconstraint forfindMatchandnubMatches.I left a note in
.hlint.yamlto only use single letter variables in rules.I used a separate commit for changes to tests but on approval will squash all commits before adding the
merge melabel.