Bodigrim pushed to branch wip/nubOrd at Glasgow Haskell Compiler / GHC
Commits:
-
ba4a2263
by Andrew Lelechenko at 2025-07-19T15:38:30+01:00
8 changed files:
- libraries/base/base.cabal.in
- libraries/base/changelog.md
- libraries/base/src/Data/List.hs
- libraries/base/src/Data/List/NonEmpty.hs
- testsuite/tests/interface-stability/base-exports.stdout
- testsuite/tests/interface-stability/base-exports.stdout-javascript-unknown-ghcjs
- testsuite/tests/interface-stability/base-exports.stdout-mingw32
- testsuite/tests/interface-stability/base-exports.stdout-ws-32
Changes:
| ... | ... | @@ -305,6 +305,7 @@ Library |
| 305 | 305 | , GHC.JS.Foreign.Callback
|
| 306 | 306 | |
| 307 | 307 | other-modules:
|
| 308 | + Data.List.Set
|
|
| 308 | 309 | System.CPUTime.Unsupported
|
| 309 | 310 | System.CPUTime.Utils
|
| 310 | 311 | if os(windows)
|
| ... | ... | @@ -2,6 +2,7 @@ |
| 2 | 2 | |
| 3 | 3 | ## 4.23.0.0 *TBA*
|
| 4 | 4 | * Add `Data.List.NonEmpty.mapMaybe`. ([CLC proposal #337](https://github.com/haskell/core-libraries-committee/issues/337))
|
| 5 | + * Add `nubOrd` / `nubOrdBy` to `Data.List` and `Data.List.NonEmpty`. ([CLC proposal #336](https://github.com/haskell/core-libraries-committee/issues/336))
|
|
| 5 | 6 | |
| 6 | 7 | ## 4.22.0.0 *TBA*
|
| 7 | 8 | * Shipped with GHC 9.14.1
|
| ... | ... | @@ -137,6 +137,7 @@ module Data.List |
| 137 | 137 | unwords,
|
| 138 | 138 | -- ** \"Set\" operations
|
| 139 | 139 | nub,
|
| 140 | + nubOrd,
|
|
| 140 | 141 | delete,
|
| 141 | 142 | (\\),
|
| 142 | 143 | union,
|
| ... | ... | @@ -157,6 +158,7 @@ module Data.List |
| 157 | 158 | -- *** User-supplied equality (replacing an @Eq@ context)
|
| 158 | 159 | -- | The predicate is assumed to define an equivalence.
|
| 159 | 160 | nubBy,
|
| 161 | + nubOrdBy,
|
|
| 160 | 162 | deleteBy,
|
| 161 | 163 | deleteFirstsBy,
|
| 162 | 164 | unionBy,
|
| ... | ... | @@ -180,12 +182,14 @@ module Data.List |
| 180 | 182 | ) where
|
| 181 | 183 | |
| 182 | 184 | import GHC.Internal.Data.Bool (otherwise)
|
| 185 | +import GHC.Internal.Data.Function (const, flip)
|
|
| 183 | 186 | import GHC.Internal.Data.List
|
| 184 | 187 | import GHC.Internal.Data.List.NonEmpty (NonEmpty(..))
|
| 185 | -import GHC.Internal.Data.Ord (Ordering(..), (<), (>))
|
|
| 188 | +import GHC.Internal.Data.Ord (Ord, compare, Ordering(..), (<), (>))
|
|
| 186 | 189 | import GHC.Internal.Int (Int)
|
| 187 | 190 | import GHC.Internal.Num ((-))
|
| 188 | 191 | import GHC.List (build)
|
| 192 | +import qualified Data.List.Set as Set
|
|
| 189 | 193 | |
| 190 | 194 | inits1, tails1 :: [a] -> [NonEmpty a]
|
| 191 | 195 | |
| ... | ... | @@ -282,3 +286,15 @@ compareLength xs n |
| 282 | 286 | (\m -> if m > 0 then LT else EQ)
|
| 283 | 287 | xs
|
| 284 | 288 | n
|
| 289 | + |
|
| 290 | +-- | Same as 'nub', but asymptotically faster, taking only /O/(/n/ log /n/) time.
|
|
| 291 | +--
|
|
| 292 | +-- @since 4.23.0.0
|
|
| 293 | +nubOrd :: Ord a => [a] -> [a]
|
|
| 294 | +nubOrd = nubOrdBy compare
|
|
| 295 | + |
|
| 296 | +-- | Overloaded version of 'Data.List.nubOrd'.
|
|
| 297 | +--
|
|
| 298 | +-- @since 4.23.0.0
|
|
| 299 | +nubOrdBy :: (a -> a -> Ordering) -> [a] -> [a]
|
|
| 300 | +nubOrdBy cmp = flip (foldr (\x acc seen -> if Set.member cmp x seen then acc seen else x : acc (Set.insert cmp x seen)) (const [])) Set.empty |
| ... | ... | @@ -94,7 +94,9 @@ module Data.List.NonEmpty ( |
| 94 | 94 | , isPrefixOf -- :: Eq a => [a] -> NonEmpty a -> Bool
|
| 95 | 95 | -- * \"Set\" operations
|
| 96 | 96 | , nub -- :: Eq a => NonEmpty a -> NonEmpty a
|
| 97 | + , nubOrd -- :: Ord a => NonEmpty a -> NonEmpty a
|
|
| 97 | 98 | , nubBy -- :: (a -> a -> Bool) -> NonEmpty a -> NonEmpty a
|
| 99 | + , nubOrdBy -- :: (a -> a -> Ordering) -> NonEmpty a -> NonEmpty a
|
|
| 98 | 100 | -- * Indexing streams
|
| 99 | 101 | , (!!) -- :: NonEmpty a -> Int -> a
|
| 100 | 102 | -- * Zipping and unzipping streams
|
| ... | ... | @@ -119,6 +121,7 @@ import qualified Prelude |
| 119 | 121 | |
| 120 | 122 | import Control.Applicative (Applicative (..), Alternative (many))
|
| 121 | 123 | import qualified Data.List as List
|
| 124 | +import qualified Data.List.Set as Set
|
|
| 122 | 125 | import qualified Data.Maybe as List (mapMaybe)
|
| 123 | 126 | import GHC.Internal.Data.Foldable hiding (length, toList)
|
| 124 | 127 | import qualified GHC.Internal.Data.Foldable as Foldable
|
| ... | ... | @@ -572,6 +575,18 @@ nub = nubBy (==) |
| 572 | 575 | nubBy :: (a -> a -> Bool) -> NonEmpty a -> NonEmpty a
|
| 573 | 576 | nubBy eq (a :| as) = a :| List.nubBy eq (List.filter (\b -> not (eq a b)) as)
|
| 574 | 577 | |
| 578 | +-- | Same as 'nub', but asymptotically faster, taking only /O/(/n/ log /n/) time.
|
|
| 579 | +--
|
|
| 580 | +-- @since 4.23.0.0
|
|
| 581 | +nubOrd :: Ord a => NonEmpty a -> NonEmpty a
|
|
| 582 | +nubOrd = nubOrdBy compare
|
|
| 583 | + |
|
| 584 | +-- | Overloaded version of 'Data.List.NonEmpty.nubOrd'.
|
|
| 585 | +--
|
|
| 586 | +-- @since 4.23.0.0
|
|
| 587 | +nubOrdBy :: (a -> a -> Ordering) -> NonEmpty a -> NonEmpty a
|
|
| 588 | +nubOrdBy cmp (y :| ys) = y :| foldr (\x acc seen -> if Set.member cmp x seen then acc seen else x : acc (Set.insert cmp x seen)) (const []) ys (Set.insert cmp y Set.empty)
|
|
| 589 | + |
|
| 575 | 590 | -- | 'transpose' for 'NonEmpty', behaves the same as 'GHC.Internal.Data.List.transpose'
|
| 576 | 591 | -- The rows/columns need not be the same length, in which case
|
| 577 | 592 | -- > transpose . transpose /= id
|
| ... | ... | @@ -1377,6 +1377,8 @@ module Data.List where |
| 1377 | 1377 | notElem :: forall (t :: * -> *) a. (GHC.Internal.Data.Foldable.Foldable t, GHC.Internal.Classes.Eq a) => a -> t a -> GHC.Internal.Types.Bool
|
| 1378 | 1378 | nub :: forall a. GHC.Internal.Classes.Eq a => [a] -> [a]
|
| 1379 | 1379 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> [a] -> [a]
|
| 1380 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => [a] -> [a]
|
|
| 1381 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> [a] -> [a]
|
|
| 1380 | 1382 | null :: forall (t :: * -> *) a. GHC.Internal.Data.Foldable.Foldable t => t a -> GHC.Internal.Types.Bool
|
| 1381 | 1383 | or :: forall (t :: * -> *). GHC.Internal.Data.Foldable.Foldable t => t GHC.Internal.Types.Bool -> GHC.Internal.Types.Bool
|
| 1382 | 1384 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> [a] -> ([a], [a])
|
| ... | ... | @@ -1471,6 +1473,8 @@ module Data.List.NonEmpty where |
| 1471 | 1473 | nonEmpty :: forall a. [a] -> GHC.Internal.Maybe.Maybe (NonEmpty a)
|
| 1472 | 1474 | nub :: forall a. GHC.Internal.Classes.Eq a => NonEmpty a -> NonEmpty a
|
| 1473 | 1475 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> NonEmpty a -> NonEmpty a
|
| 1476 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => NonEmpty a -> NonEmpty a
|
|
| 1477 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> NonEmpty a -> NonEmpty a
|
|
| 1474 | 1478 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> NonEmpty a -> ([a], [a])
|
| 1475 | 1479 | permutations :: forall a. [a] -> NonEmpty [a]
|
| 1476 | 1480 | permutations1 :: forall a. NonEmpty a -> NonEmpty (NonEmpty a)
|
| ... | ... | @@ -1377,6 +1377,8 @@ module Data.List where |
| 1377 | 1377 | notElem :: forall (t :: * -> *) a. (GHC.Internal.Data.Foldable.Foldable t, GHC.Internal.Classes.Eq a) => a -> t a -> GHC.Internal.Types.Bool
|
| 1378 | 1378 | nub :: forall a. GHC.Internal.Classes.Eq a => [a] -> [a]
|
| 1379 | 1379 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> [a] -> [a]
|
| 1380 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => [a] -> [a]
|
|
| 1381 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> [a] -> [a]
|
|
| 1380 | 1382 | null :: forall (t :: * -> *) a. GHC.Internal.Data.Foldable.Foldable t => t a -> GHC.Internal.Types.Bool
|
| 1381 | 1383 | or :: forall (t :: * -> *). GHC.Internal.Data.Foldable.Foldable t => t GHC.Internal.Types.Bool -> GHC.Internal.Types.Bool
|
| 1382 | 1384 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> [a] -> ([a], [a])
|
| ... | ... | @@ -1471,6 +1473,8 @@ module Data.List.NonEmpty where |
| 1471 | 1473 | nonEmpty :: forall a. [a] -> GHC.Internal.Maybe.Maybe (NonEmpty a)
|
| 1472 | 1474 | nub :: forall a. GHC.Internal.Classes.Eq a => NonEmpty a -> NonEmpty a
|
| 1473 | 1475 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> NonEmpty a -> NonEmpty a
|
| 1476 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => NonEmpty a -> NonEmpty a
|
|
| 1477 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> NonEmpty a -> NonEmpty a
|
|
| 1474 | 1478 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> NonEmpty a -> ([a], [a])
|
| 1475 | 1479 | permutations :: forall a. [a] -> NonEmpty [a]
|
| 1476 | 1480 | permutations1 :: forall a. NonEmpty a -> NonEmpty (NonEmpty a)
|
| ... | ... | @@ -1377,6 +1377,8 @@ module Data.List where |
| 1377 | 1377 | notElem :: forall (t :: * -> *) a. (GHC.Internal.Data.Foldable.Foldable t, GHC.Internal.Classes.Eq a) => a -> t a -> GHC.Internal.Types.Bool
|
| 1378 | 1378 | nub :: forall a. GHC.Internal.Classes.Eq a => [a] -> [a]
|
| 1379 | 1379 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> [a] -> [a]
|
| 1380 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => [a] -> [a]
|
|
| 1381 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> [a] -> [a]
|
|
| 1380 | 1382 | null :: forall (t :: * -> *) a. GHC.Internal.Data.Foldable.Foldable t => t a -> GHC.Internal.Types.Bool
|
| 1381 | 1383 | or :: forall (t :: * -> *). GHC.Internal.Data.Foldable.Foldable t => t GHC.Internal.Types.Bool -> GHC.Internal.Types.Bool
|
| 1382 | 1384 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> [a] -> ([a], [a])
|
| ... | ... | @@ -1471,6 +1473,8 @@ module Data.List.NonEmpty where |
| 1471 | 1473 | nonEmpty :: forall a. [a] -> GHC.Internal.Maybe.Maybe (NonEmpty a)
|
| 1472 | 1474 | nub :: forall a. GHC.Internal.Classes.Eq a => NonEmpty a -> NonEmpty a
|
| 1473 | 1475 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> NonEmpty a -> NonEmpty a
|
| 1476 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => NonEmpty a -> NonEmpty a
|
|
| 1477 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> NonEmpty a -> NonEmpty a
|
|
| 1474 | 1478 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> NonEmpty a -> ([a], [a])
|
| 1475 | 1479 | permutations :: forall a. [a] -> NonEmpty [a]
|
| 1476 | 1480 | permutations1 :: forall a. NonEmpty a -> NonEmpty (NonEmpty a)
|
| ... | ... | @@ -1377,6 +1377,8 @@ module Data.List where |
| 1377 | 1377 | notElem :: forall (t :: * -> *) a. (GHC.Internal.Data.Foldable.Foldable t, GHC.Internal.Classes.Eq a) => a -> t a -> GHC.Internal.Types.Bool
|
| 1378 | 1378 | nub :: forall a. GHC.Internal.Classes.Eq a => [a] -> [a]
|
| 1379 | 1379 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> [a] -> [a]
|
| 1380 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => [a] -> [a]
|
|
| 1381 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> [a] -> [a]
|
|
| 1380 | 1382 | null :: forall (t :: * -> *) a. GHC.Internal.Data.Foldable.Foldable t => t a -> GHC.Internal.Types.Bool
|
| 1381 | 1383 | or :: forall (t :: * -> *). GHC.Internal.Data.Foldable.Foldable t => t GHC.Internal.Types.Bool -> GHC.Internal.Types.Bool
|
| 1382 | 1384 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> [a] -> ([a], [a])
|
| ... | ... | @@ -1471,6 +1473,8 @@ module Data.List.NonEmpty where |
| 1471 | 1473 | nonEmpty :: forall a. [a] -> GHC.Internal.Maybe.Maybe (NonEmpty a)
|
| 1472 | 1474 | nub :: forall a. GHC.Internal.Classes.Eq a => NonEmpty a -> NonEmpty a
|
| 1473 | 1475 | nubBy :: forall a. (a -> a -> GHC.Internal.Types.Bool) -> NonEmpty a -> NonEmpty a
|
| 1476 | + nubOrd :: forall a. GHC.Internal.Classes.Ord a => NonEmpty a -> NonEmpty a
|
|
| 1477 | + nubOrdBy :: forall a. (a -> a -> GHC.Internal.Types.Ordering) -> NonEmpty a -> NonEmpty a
|
|
| 1474 | 1478 | partition :: forall a. (a -> GHC.Internal.Types.Bool) -> NonEmpty a -> ([a], [a])
|
| 1475 | 1479 | permutations :: forall a. [a] -> NonEmpty [a]
|
| 1476 | 1480 | permutations1 :: forall a. NonEmpty a -> NonEmpty (NonEmpty a)
|