diff --git a/CHANGELOG.md b/CHANGELOG.md index e644c20..28b13ac 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ *worst case* logarithmic, while maintaining their previous amortized bounds. (#26) + * Add strict left unordered folds (`foldlU'`, `foldlWithKeyU'`) + and monoidal unordered folds (`foldMapU`, `foldMapWithKeyU`). (#59) + * New `mapMWithKey` functions optimized for working in strict monads. These are used to implement the `mapM` and `sequence` methods of `Traversable`. (#46) diff --git a/src/Data/PQueue/Max.hs b/src/Data/PQueue/Max.hs index 6a58637..221d367 100644 --- a/src/Data/PQueue/Max.hs +++ b/src/Data/PQueue/Max.hs @@ -278,14 +278,20 @@ foldrU :: (a -> b -> b) -> b -> MaxQueue a -> b foldrU f z (MaxQ q) = Min.foldrU (flip (foldr f)) z q -- | /O(n)/. Unordered monoidal fold on a priority queue. +-- +-- @since 1.4.2 foldMapU :: Monoid m => (a -> m) -> MaxQueue a -> m foldMapU f (MaxQ q) = Min.foldMapU (f . unDown) q --- | /O(n)/. Unordered left fold on a priority queue. +-- | /O(n)/. Unordered left fold on a priority queue. This is rarely +-- what you want; 'foldrU' and 'foldlU'' are more likely to perform +-- well. foldlU :: (b -> a -> b) -> b -> MaxQueue a -> b foldlU f z (MaxQ q) = Min.foldlU (foldl f) z q -- | /O(n)/. Unordered strict left fold on a priority queue. +-- +-- @since 1.4.2 foldlU' :: (b -> a -> b) -> b -> MaxQueue a -> b foldlU' f z (MaxQ q) = Min.foldlU' (foldl' f) z q diff --git a/src/Data/PQueue/Prio/Internals.hs b/src/Data/PQueue/Prio/Internals.hs index b3e2ab8..6d3e33e 100644 --- a/src/Data/PQueue/Prio/Internals.hs +++ b/src/Data/PQueue/Prio/Internals.hs @@ -624,18 +624,22 @@ foldrWithKeyU _ z Empty = z foldrWithKeyU f z (MinPQ _ k a ts) = f k a (foldrWithKeyF_ f (const id) ts z) -- | /O(n)/. An unordered monoidal fold over the elements of the queue, in no particular order. +-- +-- @since 1.4.2 foldMapWithKeyU :: Monoid m => (k -> a -> m) -> MinPQueue k a -> m foldMapWithKeyU _ Empty = mempty foldMapWithKeyU f (MinPQ _ k a ts) = f k a `mappend` foldMapWithKey_ f ts -- | /O(n)/. An unordered left fold over the elements of the queue, in no --- particular order. This is rarely what you want; 'foldrWithKeyU' and +-- particular order. This is rarely what you want; 'foldrWithKeyU' and -- 'foldlWithKeyU'' are more likely to perform well. foldlWithKeyU :: (b -> k -> a -> b) -> b -> MinPQueue k a -> b foldlWithKeyU _ z Empty = z foldlWithKeyU f z0 (MinPQ _ k0 a0 ts) = foldlWithKeyF_ (\k a z -> f z k a) (const id) ts (f z0 k0 a0) -- | /O(n)/. An unordered strict left fold over the elements of the queue, in no particular order. +-- +-- @since 1.4.2 foldlWithKeyU' :: (b -> k -> a -> b) -> b -> MinPQueue k a -> b foldlWithKeyU' _ z Empty = z foldlWithKeyU' f !z0 (MinPQ _ k0 a0 ts) = foldlWithKey'_ f (f z0 k0 a0) ts @@ -723,7 +727,7 @@ mapKeysMonoF f fCh ts0 = case ts0 of -- | /O(log n)/. @seqSpine q r@ forces the spine of @q@ and returns @r@. -- --- Note: The spine of a 'MinPQueue' is stored somewhat lazily. Most operations +-- Note: The spine of a 'MinPQueue' is stored somewhat lazily. Most operations -- take great care to prevent chains of thunks from accumulating along the -- spine to the detriment of performance. However, 'mapKeysMonotonic' can leave -- expensive thunks in the structure and repeated applications of that function diff --git a/src/Data/PQueue/Prio/Max/Internals.hs b/src/Data/PQueue/Prio/Max/Internals.hs index 8e8c186..49a6107 100644 --- a/src/Data/PQueue/Prio/Max/Internals.hs +++ b/src/Data/PQueue/Prio/Max/Internals.hs @@ -290,7 +290,7 @@ mapKeys :: Ord k' => (k -> k') -> MaxPQueue k a -> MaxPQueue k' a mapKeys f (MaxPQ q) = MaxPQ (Q.mapKeys (fmap f) q) -- | /O(n)/. @'mapKeysMonotonic' f q == 'mapKeys' f q@, but only works when @f@ is strictly --- monotonic. /The precondition is not checked./ This function has better performance than +-- monotonic. /The precondition is not checked./ This function has better performance than -- 'mapKeys'. mapKeysMonotonic :: (k -> k') -> MaxPQueue k a -> MaxPQueue k' a mapKeysMonotonic f (MaxPQ q) = MaxPQ (Q.mapKeysMonotonic (fmap f) q) @@ -468,27 +468,33 @@ foldrWithKeyU :: (k -> a -> b -> b) -> b -> MaxPQueue k a -> b foldrWithKeyU f z (MaxPQ q) = Q.foldrWithKeyU (f . unDown) z q -- | /O(n)/. An unordered monoidal fold over the elements of the queue, in no particular order. +-- +-- @since 1.4.2 foldMapWithKeyU :: Monoid m => (k -> a -> m) -> MaxPQueue k a -> m foldMapWithKeyU f (MaxPQ q) = Q.foldMapWithKeyU (f . unDown) q -- | /O(n)/. An unordered left fold over the elements of the queue, in no --- particular order. This is rarely what you want; 'foldrU' and 'foldlU'' are +-- particular order. This is rarely what you want; 'foldrU' and 'foldlU'' are -- more likely to perform well. foldlU :: (b -> a -> b) -> b -> MaxPQueue k a -> b foldlU f = foldlWithKeyU (const . f) -- | /O(n)/. An unordered strict left fold over the elements of the queue, in no -- particular order. +-- +-- @since 1.4.2 foldlU' :: (b -> a -> b) -> b -> MaxPQueue k a -> b foldlU' f = foldlWithKeyU' (const . f) -- | /O(n)/. An unordered left fold over the elements of the queue, in no --- particular order. This is rarely what you want; 'foldrWithKeyU' and +-- particular order. This is rarely what you want; 'foldrWithKeyU' and -- 'foldlWithKeyU'' are more likely to perform well. foldlWithKeyU :: (b -> k -> a -> b) -> b -> MaxPQueue k a -> b foldlWithKeyU f z0 (MaxPQ q) = Q.foldlWithKeyU (\z -> f z . unDown) z0 q -- | /O(n)/. An unordered left fold over the elements of the queue, in no particular order. +-- +-- @since 1.4.2 foldlWithKeyU' :: (b -> k -> a -> b) -> b -> MaxPQueue k a -> b foldlWithKeyU' f z0 (MaxPQ q) = Q.foldlWithKeyU' (\z -> f z . unDown) z0 q diff --git a/src/Data/PQueue/Prio/Min.hs b/src/Data/PQueue/Prio/Min.hs index b76717a..a38d85f 100644 --- a/src/Data/PQueue/Prio/Min.hs +++ b/src/Data/PQueue/Prio/Min.hs @@ -317,13 +317,15 @@ assocsU :: MinPQueue k a -> [(k, a)] assocsU = toListU -- | /O(n)/. An unordered left fold over the elements of the queue, in no --- particular order. This is rarely what you want; 'foldrU' and 'foldlU'' are +-- particular order. This is rarely what you want; 'foldrU' and 'foldlU'' are -- more likely to perform well. foldlU :: (b -> a -> b) -> b -> MinPQueue k a -> b foldlU f = foldlWithKeyU (const . f) -- | /O(n)/. An unordered strict left fold over the elements of the queue, in no -- particular order. +-- +-- @since 1.4.2 foldlU' :: (b -> a -> b) -> b -> MinPQueue k a -> b foldlU' f = foldlWithKeyU' (const . f)