From 576b86d58ab1d9a35aae38d7a18661fe626425f8 Mon Sep 17 00:00:00 2001 From: konsumlamm Date: Thu, 6 Mar 2025 12:44:01 +0100 Subject: [PATCH] More `coerce` --- src/BinomialQueue/Max.hs | 72 ++++++++--------- src/Data/PQueue/Max.hs | 67 ++++++++-------- src/Data/PQueue/Prio/Max/Internals.hs | 106 ++++++++++---------------- 3 files changed, 102 insertions(+), 143 deletions(-) diff --git a/src/BinomialQueue/Max.hs b/src/BinomialQueue/Max.hs index f21c0cc..cf9368d 100644 --- a/src/BinomialQueue/Max.hs +++ b/src/BinomialQueue/Max.hs @@ -88,7 +88,6 @@ module BinomialQueue.Max ( import Prelude hiding (null, take, drop, takeWhile, dropWhile, splitAt, span, break, (!!), filter, map) import Data.Coerce (coerce) -import Data.Bifunctor (bimap) import qualified Data.List as List import Data.Maybe (fromMaybe) @@ -103,11 +102,11 @@ findMax = fromMaybe (error "Error: findMax called on empty queue") . getMax -- | \(O(1)\). The top (maximum) element of the queue, if there is one. getMax :: Ord a => MaxQueue a -> Maybe a -getMax (MaxQueue q) = unDown <$> MinQ.getMin q +getMax = coerce MinQ.getMin -- | \(O(\log n)\). Deletes the maximum element. If the queue is empty, does nothing. deleteMax :: Ord a => MaxQueue a -> MaxQueue a -deleteMax = MaxQueue . MinQ.deleteMin . unMaxQueue +deleteMax = coerce MinQ.deleteMin -- | \(O(\log n)\). Extracts the maximum element. Throws an error on an empty queue. deleteFindMax :: Ord a => MaxQueue a -> (a, MaxQueue a) @@ -115,9 +114,7 @@ deleteFindMax = fromMaybe (error "Error: deleteFindMax called on empty queue") . -- | \(O(\log n)\). Extract the top (maximum) element of the sequence, if there is one. maxView :: Ord a => MaxQueue a -> Maybe (a, MaxQueue a) -maxView (MaxQueue q) = case MinQ.minView q of - Just (Down a, q') -> Just (a, MaxQueue q') - Nothing -> Nothing +maxView = coerce MinQ.minView -- | \(O(k \log n)\). Index (subscript) operator, starting from 0. @queue !! k@ returns the @(k+1)@th largest -- element in the queue. Equivalent to @toDescList queue !! k@. @@ -130,19 +127,17 @@ q !! n = toDescList q List.!! n -- | 'takeWhile', applied to a predicate @p@ and a queue @queue@, returns the -- longest prefix (possibly empty) of @queue@ of elements that satisfy @p@. takeWhile :: Ord a => (a -> Bool) -> MaxQueue a -> [a] -takeWhile p = coerce . MinQ.takeWhile (p . unDown) . unMaxQueue +takeWhile = coerce MinQ.takeWhile -- | 'dropWhile' @p queue@ returns the queue remaining after 'takeWhile' @p queue@. dropWhile :: Ord a => (a -> Bool) -> MaxQueue a -> MaxQueue a -dropWhile p = MaxQueue . MinQ.dropWhile (p . unDown) . unMaxQueue +dropWhile = coerce MinQ.dropWhile -- | 'span', applied to a predicate @p@ and a queue @queue@, returns a tuple where -- first element is longest prefix (possibly empty) of @queue@ of elements that -- satisfy @p@ and second element is the remainder of the queue. span :: Ord a => (a -> Bool) -> MaxQueue a -> ([a], MaxQueue a) -span p (MaxQueue queue) - | (front, rear) <- MinQ.span (p . unDown) queue - = (coerce front, MaxQueue rear) +span = coerce MinQ.span -- | 'break', applied to a predicate @p@ and a queue @queue@, returns a tuple where -- first element is longest prefix (possibly empty) of @queue@ of elements that @@ -159,73 +154,67 @@ take n = List.take n . toDescList -- | \(O(k \log n)\). 'drop' @k@, applied to a queue @queue@, returns @queue@ with the greatest @k@ elements deleted, -- or an empty queue if @k >= 'size' queue@. drop :: Ord a => Int -> MaxQueue a -> MaxQueue a -drop n (MaxQueue queue) = MaxQueue (MinQ.drop n queue) +drop = coerce MinQ.drop -- | \(O(k \log n)\). Equivalent to @('take' k queue, 'drop' k queue)@. splitAt :: Ord a => Int -> MaxQueue a -> ([a], MaxQueue a) -splitAt n (MaxQueue queue) - | (l, r) <- MinQ.splitAt n queue - = (coerce l, MaxQueue r) +splitAt = coerce MinQ.splitAt -- | \(O(n)\). Returns the queue with all elements not satisfying @p@ removed. filter :: Ord a => (a -> Bool) -> MaxQueue a -> MaxQueue a -filter p = MaxQueue . MinQ.filter (p . unDown) . unMaxQueue +filter = coerce MinQ.filter -- | \(O(n)\). Returns a pair where the first queue contains all elements satisfying @p@, and the second queue -- contains all elements not satisfying @p@. partition :: Ord a => (a -> Bool) -> MaxQueue a -> (MaxQueue a, MaxQueue a) -partition p = go . unMaxQueue - where - go queue - | (l, r) <- MinQ.partition (p . unDown) queue - = (MaxQueue l, MaxQueue r) +partition = coerce MinQ.partition -- | \(O(n)\). Creates a new priority queue containing the images of the elements of this queue. -- Equivalent to @'fromList' . 'Data.List.map' f . toList@. map :: Ord b => (a -> b) -> MaxQueue a -> MaxQueue b -map f = MaxQueue . MinQ.map (fmap f) . unMaxQueue +map = coerce MinQ.map {-# INLINE toList #-} -- | \(O(n \log n)\). Returns the elements of the priority queue in descending order. Equivalent to 'toDescList'. -- -- If the order of the elements is irrelevant, consider using 'toListU'. toList :: Ord a => MaxQueue a -> [a] -toList = coerce . MinQ.toAscList . unMaxQueue +toList = coerce MinQ.toAscList toAscList :: Ord a => MaxQueue a -> [a] -toAscList = coerce . MinQ.toDescList . unMaxQueue +toAscList = coerce MinQ.toDescList toDescList :: Ord a => MaxQueue a -> [a] -toDescList = coerce . MinQ.toAscList . unMaxQueue +toDescList = coerce MinQ.toAscList -- | \(O(n \log n)\). Performs a right fold on the elements of a priority queue in descending order. foldrDesc :: Ord a => (a -> b -> b) -> b -> MaxQueue a -> b -foldrDesc f z (MaxQueue q) = MinQ.foldrAsc (flip (foldr f)) z q +foldrDesc f z (MaxQueue q) = MinQ.foldrAsc (coerce f) z q -- | \(O(n \log n)\). Performs a right fold on the elements of a priority queue in ascending order. foldrAsc :: Ord a => (a -> b -> b) -> b -> MaxQueue a -> b -foldrAsc f z (MaxQueue q) = MinQ.foldrDesc (flip (foldr f)) z q +foldrAsc f z (MaxQueue q) = MinQ.foldrDesc (coerce f) z q -- | \(O(n \log n)\). Performs a left fold on the elements of a priority queue in ascending order. foldlAsc :: Ord a => (b -> a -> b) -> b -> MaxQueue a -> b -foldlAsc f z (MaxQueue q) = MinQ.foldlDesc (foldl f) z q +foldlAsc f z (MaxQueue q) = MinQ.foldlDesc (coerce f) z q -- | \(O(n \log n)\). Performs a left fold on the elements of a priority queue in descending order. foldlDesc :: Ord a => (b -> a -> b) -> b -> MaxQueue a -> b -foldlDesc f z (MaxQueue q) = MinQ.foldlAsc (foldl f) z q +foldlDesc f z (MaxQueue q) = MinQ.foldlAsc (coerce f) z q {-# INLINE fromAscList #-} -- | \(O(n)\). Constructs a priority queue from an ascending list. /Warning/: Does not check the precondition. fromAscList :: [a] -> MaxQueue a -fromAscList = MaxQueue . MinQ.fromDescList . coerce +fromAscList = coerce MinQ.fromDescList {-# INLINE fromDescList #-} -- | \(O(n)\). Constructs a priority queue from a descending list. /Warning/: Does not check the precondition. fromDescList :: [a] -> MaxQueue a -fromDescList = MaxQueue . MinQ.fromAscList . coerce +fromDescList = coerce MinQ.fromAscList fromList :: Ord a => [a] -> MaxQueue a -fromList = MaxQueue . MinQ.fromList . coerce +fromList = coerce MinQ.fromList -- | Equivalent to 'toListU'. elemsU :: MaxQueue a -> [a] @@ -233,7 +222,7 @@ elemsU = toListU -- | Convert to a list in an arbitrary order. toListU :: MaxQueue a -> [a] -toListU = coerce . MinQ.toListU . unMaxQueue +toListU = coerce MinQ.toListU -- | Get the number of elements in a 'MaxQueue'. size :: MaxQueue a -> Int @@ -243,35 +232,34 @@ empty :: MaxQueue a empty = MaxQueue MinQ.empty foldMapU :: Monoid m => (a -> m) -> MaxQueue a -> m -foldMapU f = MinQ.foldMapU (f . unDown) . unMaxQueue +foldMapU f = MinQ.foldMapU (coerce f) . unMaxQueue seqSpine :: MaxQueue a -> b -> b seqSpine = MinQ.seqSpine . unMaxQueue foldlU :: (b -> a -> b) -> b -> MaxQueue a -> b -foldlU f b = MinQ.foldlU (\acc (Down a) -> f acc a) b . unMaxQueue +foldlU f b = MinQ.foldlU (coerce f) b . unMaxQueue foldlU' :: (b -> a -> b) -> b -> MaxQueue a -> b -foldlU' f b = MinQ.foldlU' (\acc (Down a) -> f acc a) b . unMaxQueue +foldlU' f b = MinQ.foldlU' (coerce f) b . unMaxQueue foldrU :: (a -> b -> b) -> b -> MaxQueue a -> b -foldrU c n = MinQ.foldrU (c . unDown) n . unMaxQueue +foldrU c n = MinQ.foldrU (coerce c) n . unMaxQueue null :: MaxQueue a -> Bool null = MinQ.null . unMaxQueue singleton :: a -> MaxQueue a -singleton = MaxQueue . MinQ.singleton . Down +singleton = coerce MinQ.singleton mapMaybe :: Ord b => (a -> Maybe b) -> MaxQueue a -> MaxQueue b -mapMaybe f = MaxQueue . MinQ.mapMaybe (coerce f) . unMaxQueue +mapMaybe = coerce MinQ.mapMaybe insert :: Ord a => a -> MaxQueue a -> MaxQueue a -insert a (MaxQueue q) = MaxQueue (MinQ.insert (Down a) q) +insert = coerce MinQ.insert mapEither :: (Ord b, Ord c) => (a -> Either b c) -> MaxQueue a -> (MaxQueue b, MaxQueue c) -mapEither f (MaxQueue q) = case MinQ.mapEither (bimap Down Down . f . unDown) q of - (l, r) -> (MaxQueue l, MaxQueue r) +mapEither = coerce MinQ.mapEither union :: Ord a => MaxQueue a -> MaxQueue a -> MaxQueue a union (MaxQueue a) (MaxQueue b) = MaxQueue (MinQ.union a b) diff --git a/src/Data/PQueue/Max.hs b/src/Data/PQueue/Max.hs index 6f6f417..30c7fec 100644 --- a/src/Data/PQueue/Max.hs +++ b/src/Data/PQueue/Max.hs @@ -169,11 +169,11 @@ findMax = fromMaybe (error "Error: findMax called on empty queue") . getMax -- | \(O(1)\). The top (maximum) element of the queue, if there is one. getMax :: MaxQueue a -> Maybe a -getMax (MaxQ q) = unDown <$> Min.getMin q +getMax = coerce Min.getMin -- | \(O(\log n)\). Deletes the maximum element of the queue. Does nothing on an empty queue. deleteMax :: Ord a => MaxQueue a -> MaxQueue a -deleteMax (MaxQ q) = MaxQ (Min.deleteMin q) +deleteMax = coerce Min.deleteMin -- | \(O(\log n)\). Extracts the maximum element of the queue. Throws an error on an empty queue. deleteFindMax :: Ord a => MaxQueue a -> (a, MaxQueue a) @@ -181,10 +181,7 @@ deleteFindMax = fromMaybe (error "Error: deleteFindMax called on empty queue") . -- | \(O(\log n)\). Extract the top (maximum) element of the sequence, if there is one. maxView :: Ord a => MaxQueue a -> Maybe (a, MaxQueue a) -maxView (MaxQ q) = case Min.minView q of - Nothing -> Nothing - Just (Down x, q') - -> Just (x, MaxQ q') +maxView = coerce Min.minView -- | \(O(\log n)\). Delete the top (maximum) element of the sequence, if there is one. delete :: Ord a => MaxQueue a -> Maybe (MaxQueue a) @@ -192,11 +189,11 @@ delete = fmap snd . maxView -- | \(O(1)\). Construct a priority queue with a single element. singleton :: a -> MaxQueue a -singleton = MaxQ . Min.singleton . Down +singleton = coerce Min.singleton -- | \(O(1)\). Insert an element into the priority queue. insert :: Ord a => a -> MaxQueue a -> MaxQueue a -x `insert` MaxQ q = MaxQ (Down x `Min.insert` q) +insert = coerce Min.insert -- | \(O(\log min(n_1,n_2))\). Take the union of two priority queues. union :: Ord a => MaxQueue a -> MaxQueue a -> MaxQueue a @@ -204,43 +201,41 @@ MaxQ q1 `union` MaxQ q2 = MaxQ (q1 `Min.union` q2) -- | Takes the union of a list of priority queues. Equivalent to @'foldl' 'union' 'empty'@. unions :: Ord a => [MaxQueue a] -> MaxQueue a -unions qs = MaxQ (Min.unions [q | MaxQ q <- qs]) +unions = coerce Min.unions -- | \(O(k \log n)\). Returns the @(k+1)@th largest element of the queue. (!!) :: Ord a => MaxQueue a -> Int -> a -MaxQ q !! n = unDown ((Min.!!) q n) +(!!) = coerce (Min.!!) {-# INLINE take #-} -- | \(O(k \log n)\). Returns the list of the @k@ largest elements of the queue, in descending order, or -- all elements of the queue, if @k >= n@. take :: Ord a => Int -> MaxQueue a -> [a] -take k (MaxQ q) = [a | Down a <- Min.take k q] +take = coerce Min.take -- | \(O(k \log n)\). Returns the queue with the @k@ largest elements deleted, or the empty queue if @k >= n@. drop :: Ord a => Int -> MaxQueue a -> MaxQueue a -drop k (MaxQ q) = MaxQ (Min.drop k q) +drop = coerce Min.drop -- | \(O(k \log n)\). Equivalent to @(take k queue, drop k queue)@. splitAt :: Ord a => Int -> MaxQueue a -> ([a], MaxQueue a) -splitAt k (MaxQ q) = (coerce xs, MaxQ q') where - (xs, q') = Min.splitAt k q +splitAt = coerce Min.splitAt -- | 'takeWhile', applied to a predicate @p@ and a queue @queue@, returns the -- longest prefix (possibly empty) of @queue@ of elements that satisfy @p@. takeWhile :: Ord a => (a -> Bool) -> MaxQueue a -> [a] -takeWhile p (MaxQ q) = coerce (Min.takeWhile (p . unDown) q) +takeWhile = coerce Min.takeWhile -- | 'dropWhile' @p queue@ returns the queue remaining after 'takeWhile' @p queue@. dropWhile :: Ord a => (a -> Bool) -> MaxQueue a -> MaxQueue a -dropWhile p (MaxQ q) = MaxQ (Min.dropWhile (p . unDown) q) +dropWhile = coerce Min.dropWhile -- | 'span', applied to a predicate @p@ and a queue @queue@, returns a tuple where -- first element is longest prefix (possibly empty) of @queue@ of elements that -- satisfy @p@ and second element is the remainder of the queue. -- span :: Ord a => (a -> Bool) -> MaxQueue a -> ([a], MaxQueue a) -span p (MaxQ q) = (coerce xs, MaxQ q') where - (xs, q') = Min.span (p . unDown) q +span = coerce Min.span -- | 'break', applied to a predicate @p@ and a queue @queue@, returns a tuple where -- first element is longest prefix (possibly empty) of @queue@ of elements that @@ -250,27 +245,25 @@ break p = span (not . p) -- | \(O(n)\). Returns a queue of those elements which satisfy the predicate. filter :: Ord a => (a -> Bool) -> MaxQueue a -> MaxQueue a -filter p (MaxQ q) = MaxQ (Min.filter (p . unDown) q) +filter = coerce Min.filter -- | \(O(n)\). Returns a pair of queues, where the left queue contains those elements that satisfy the predicate, -- and the right queue contains those that do not. partition :: Ord a => (a -> Bool) -> MaxQueue a -> (MaxQueue a, MaxQueue a) -partition p (MaxQ q) = (MaxQ q0, MaxQ q1) - where (q0, q1) = Min.partition (p . unDown) q +partition = coerce Min.partition -- | \(O(n)\). Maps a function over the elements of the queue, and collects the 'Just' values. mapMaybe :: Ord b => (a -> Maybe b) -> MaxQueue a -> MaxQueue b -mapMaybe f (MaxQ q) = MaxQ (Min.mapMaybe (\(Down x) -> Down <$> f x) q) +mapMaybe = coerce Min.mapMaybe -- | \(O(n)\). Maps a function over the elements of the queue, and separates the 'Left' and 'Right' values. mapEither :: (Ord b, Ord c) => (a -> Either b c) -> MaxQueue a -> (MaxQueue b, MaxQueue c) -mapEither f (MaxQ q) = (MaxQ q0, MaxQ q1) - where (q0, q1) = Min.mapEither (either (Left . Down) (Right . Down) . f . unDown) q +mapEither = coerce Min.mapEither -- | \(O(n)\). Creates a new priority queue containing the images of the elements of this queue. -- Equivalent to @'fromList' . 'Data.List.map' f . toList@. map :: Ord b => (a -> b) -> MaxQueue a -> MaxQueue b -map f (MaxQ q) = MaxQ (Min.map (\(Down x) -> Down (f x)) q) +map = coerce Min.map -- | \(O(n)\). Assumes that the function it is given is (weakly) monotonic -- (meaning that @x <= y@ implies @f x <= f y@), and @@ -285,25 +278,25 @@ mapU = mapMonotonic -- | \(O(n)\). Unordered right fold on a priority queue. foldrU :: (a -> b -> b) -> b -> MaxQueue a -> b -foldrU f z (MaxQ q) = Min.foldrU (flip (foldr f)) z q +foldrU f z (MaxQ q) = Min.foldrU (coerce 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 +foldMapU f (MaxQ q) = Min.foldMapU (coerce f) q -- | \(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 +foldlU f z (MaxQ q) = Min.foldlU (coerce 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 +foldlU' f z (MaxQ q) = Min.foldlU' (coerce f) z q {-# INLINE elemsU #-} -- | Equivalent to 'toListU'. @@ -313,7 +306,7 @@ elemsU = toListU {-# INLINE toListU #-} -- | \(O(n)\). Returns a list of the elements of the priority queue, in no particular order. toListU :: MaxQueue a -> [a] -toListU (MaxQ q) = coerce (Min.toListU q) +toListU = coerce Min.toListU -- | \(O(n \log n)\). Performs a right-fold on the elements of a priority queue in ascending order. -- @'foldrAsc' f z q == 'foldlDesc' (flip f) z q@. @@ -327,11 +320,11 @@ foldlAsc = foldrDesc . flip -- | \(O(n \log n)\). Performs a right-fold on the elements of a priority queue in descending order. foldrDesc :: Ord a => (a -> b -> b) -> b -> MaxQueue a -> b -foldrDesc f z (MaxQ q) = Min.foldrAsc (flip (foldr f)) z q +foldrDesc f z (MaxQ q) = Min.foldrAsc (coerce f) z q -- | \(O(n \log n)\). Performs a left-fold on the elements of a priority queue in descending order. foldlDesc :: Ord a => (b -> a -> b) -> b -> MaxQueue a -> b -foldlDesc f z (MaxQ q) = Min.foldlAsc (foldl f) z q +foldlDesc f z (MaxQ q) = Min.foldlAsc (coerce f) z q {-# INLINE toAscList #-} -- | \(O(n \log n)\). Extracts the elements of the priority queue in ascending order. @@ -350,26 +343,26 @@ toDescList q = build (\c nil -> foldrDesc c nil q) -- -- If the order of the elements is irrelevant, consider using 'toListU'. toList :: Ord a => MaxQueue a -> [a] -toList (MaxQ q) = coerce (Min.toList q) +toList = coerce Min.toList {-# INLINE fromAscList #-} -- | \(O(n)\). Constructs a priority queue from an ascending list. /Warning/: Does not check the precondition. fromAscList :: [a] -> MaxQueue a -fromAscList = MaxQ . Min.fromDescList . coerce +fromAscList = coerce Min.fromDescList {-# INLINE fromDescList #-} -- | \(O(n)\). Constructs a priority queue from a descending list. /Warning/: Does not check the precondition. fromDescList :: [a] -> MaxQueue a -fromDescList = MaxQ . Min.fromAscList . coerce +fromDescList = coerce Min.fromAscList {-# INLINE fromList #-} -- | \(O(n \log n)\). Constructs a priority queue from an unordered list. fromList :: Ord a => [a] -> MaxQueue a -fromList = MaxQ . Min.fromList . coerce +fromList = coerce Min.fromList -- | \(O(n)\). Constructs a priority queue from the keys of a 'Prio.MaxPQueue'. keysQueue :: Prio.MaxPQueue k a -> MaxQueue k -keysQueue (Prio.MaxPQ q) = MaxQ (Min.keysQueue q) +keysQueue = coerce Min.keysQueue -- | \(O(\log n)\). @seqSpine q r@ forces the spine of @q@ and returns @r@. -- diff --git a/src/Data/PQueue/Prio/Max/Internals.hs b/src/Data/PQueue/Prio/Max/Internals.hs index dcd4b61..139d5b8 100644 --- a/src/Data/PQueue/Prio/Max/Internals.hs +++ b/src/Data/PQueue/Prio/Max/Internals.hs @@ -105,6 +105,7 @@ module Data.PQueue.Prio.Max.Internals ( ) where +import Data.Coerce import Data.Maybe (fromMaybe) import Data.PQueue.Internals.Down import Data.PQueue.Prio.Internals (MinPQueue) @@ -145,9 +146,6 @@ newtype MaxPQueue k a = MaxPQ (MinPQueue (Down k) a) instance (NFData k, NFData a) => NFData (MaxPQueue k a) where rnf (MaxPQ q) = rnf q -first' :: (a -> b) -> (a, c) -> (b, c) -first' f (a, c) = (f a, c) - instance Ord k => Semigroup (MaxPQueue k a) where (<>) = union stimes = stimesMonoid @@ -211,12 +209,12 @@ empty = MaxPQ Q.empty -- | \(O(1)\). Constructs a singleton priority queue. singleton :: k -> a -> MaxPQueue k a -singleton k a = MaxPQ (Q.singleton (Down k) a) +singleton = coerce Q.singleton -- | Amortized \(O(1)\), worst-case \(O(\log n)\). Inserts -- an element with the specified key into the queue. insert :: Ord k => k -> a -> MaxPQueue k a -> MaxPQueue k a -insert k a (MaxPQ q) = MaxPQ (Q.insert (Down k) a q) +insert = coerce Q.insert -- | \(O(n)\) (an earlier implementation had \(O(1)\) but was buggy). -- Insert an element with the specified key into the priority queue, @@ -224,16 +222,16 @@ insert k a (MaxPQ q) = MaxPQ (Q.insert (Down k) a q) -- inserted one. {-# DEPRECATED insertBehind "This function is not reliable." #-} insertBehind :: Ord k => k -> a -> MaxPQueue k a -> MaxPQueue k a -insertBehind k a (MaxPQ q) = MaxPQ (Q.insertBehind (Down k) a q) +insertBehind = coerce Q.insertBehind -- | Amortized \(O(\log \min(n_1,n_2))\), worst-case \(O(\log \max(n_1,n_2))\). Returns the union -- of the two specified queues. union :: Ord k => MaxPQueue k a -> MaxPQueue k a -> MaxPQueue k a -MaxPQ q1 `union` MaxPQ q2 = MaxPQ (q1 `Q.union` q2) +union = coerce Q.union -- | The union of a list of queues: (@'unions' == 'List.foldl' 'union' 'empty'@). unions :: Ord k => [MaxPQueue k a] -> MaxPQueue k a -unions qs = MaxPQ (Q.unions [q | MaxPQ q <- qs]) +unions = coerce Q.unions -- | \(O(1)\). Checks if this priority queue is empty. null :: MaxPQueue k a -> Bool @@ -249,13 +247,11 @@ findMax = fromMaybe (error "Error: findMax called on an empty queue") . getMax -- | \(O(1)\). The maximal (key, element) in the queue, if the queue is nonempty. getMax :: MaxPQueue k a -> Maybe (k, a) -getMax (MaxPQ q) = do - (Down k, a) <- Q.getMin q - return (k, a) +getMax = coerce Q.getMin -- | \(O(\log n)\). Delete and find the element with the maximum key. Calls 'error' if empty. deleteMax :: Ord k => MaxPQueue k a -> MaxPQueue k a -deleteMax (MaxPQ q) = MaxPQ (Q.deleteMin q) +deleteMax = coerce Q.deleteMin -- | \(O(\log n)\). Delete and find the element with the maximum key. Calls 'error' if empty. deleteFindMax :: Ord k => MaxPQueue k a -> ((k, a), MaxPQueue k a) @@ -274,14 +270,14 @@ adjustMaxA = adjustMaxWithKeyA . const -- | \(O(1)\). Alter the value at the maximum key. If the queue is empty, does nothing. adjustMaxWithKey :: (k -> a -> a) -> MaxPQueue k a -> MaxPQueue k a -adjustMaxWithKey f (MaxPQ q) = MaxPQ (Q.adjustMinWithKey (f . unDown) q) +adjustMaxWithKey = coerce Q.adjustMinWithKey -- | \(O(1)\) per operation. Alter the value at the maximum key in an -- 'Applicative' context. If the queue is empty, does nothing. -- -- @since 1.4.2 adjustMaxWithKeyA :: Applicative f => (k -> a -> f a) -> MaxPQueue k a -> f (MaxPQueue k a) -adjustMaxWithKeyA f (MaxPQ q) = PrioInternals.adjustMinWithKeyA' MaxPQ (f . unDown) q +adjustMaxWithKeyA f (MaxPQ q) = PrioInternals.adjustMinWithKeyA' MaxPQ (coerce f) q -- | \(O(\log n)\). (Actually \(O(1)\) if there's no deletion.) Update the value at the maximum key. -- If the queue is empty, does nothing. @@ -299,7 +295,7 @@ updateMaxA = updateMaxWithKeyA . const -- | \(O(\log n)\). (Actually \(O(1)\) if there's no deletion.) Update the value at the maximum key. -- If the queue is empty, does nothing. updateMaxWithKey :: Ord k => (k -> a -> Maybe a) -> MaxPQueue k a -> MaxPQueue k a -updateMaxWithKey f (MaxPQ q) = MaxPQ (Q.updateMinWithKey (f . unDown) q) +updateMaxWithKey = coerce Q.updateMinWithKey -- | \(O(\log n)\) per operation. (Actually \(O(1)\) if there's no deletion.) Update -- the value at the maximum key in an 'Applicative' context. If the queue is @@ -307,7 +303,7 @@ updateMaxWithKey f (MaxPQ q) = MaxPQ (Q.updateMinWithKey (f . unDown) q) -- -- @since 1.4.2 updateMaxWithKeyA :: (Applicative f, Ord k) => (k -> a -> f (Maybe a)) -> MaxPQueue k a -> f (MaxPQueue k a) -updateMaxWithKeyA f (MaxPQ q) = PrioInternals.updateMinWithKeyA' MaxPQ (f . unDown) q +updateMaxWithKeyA f (MaxPQ q) = PrioInternals.updateMinWithKeyA' MaxPQ (coerce f) q -- | \(O(\log n)\). Retrieves the value associated with the maximum key of the queue, and the queue -- stripped of that element, or 'Nothing' if passed an empty queue. @@ -319,9 +315,7 @@ maxView q = do -- | \(O(\log n)\). Retrieves the maximal (key, value) pair of the map, and the map stripped of that -- element, or 'Nothing' if passed an empty map. maxViewWithKey :: Ord k => MaxPQueue k a -> Maybe ((k, a), MaxPQueue k a) -maxViewWithKey (MaxPQ q) = do - ((Down k, a), q') <- Q.minViewWithKey q - return ((k, a), MaxPQ q') +maxViewWithKey = coerce Q.minViewWithKey -- | \(O(n)\). Map a function over all values in the queue. map :: (a -> b) -> MaxPQueue k a -> MaxPQueue k b @@ -329,11 +323,11 @@ map = mapWithKey . const -- | \(O(n)\). Map a function over all values in the queue. mapWithKey :: (k -> a -> b) -> MaxPQueue k a -> MaxPQueue k b -mapWithKey f (MaxPQ q) = MaxPQ (Q.mapWithKey (f . unDown) q) +mapWithKey = coerce Q.mapWithKey -- | \(O(n)\). Map a function over all values in the queue. mapKeys :: Ord k' => (k -> k') -> MaxPQueue k a -> MaxPQueue k' a -mapKeys f (MaxPQ q) = MaxPQ (Q.mapKeys (fmap f) q) +mapKeys = coerce Q.mapKeys -- | \(O(n)\). @'mapKeysMonotonic' f q == 'mapKeys' f q@, but only works when -- @f@ is (weakly) monotonic (meaning that @x <= y@ implies @f x <= f y@). @@ -342,21 +336,21 @@ mapKeys f (MaxPQ q) = MaxPQ (Q.mapKeys (fmap f) q) -- Note: if the given function returns bottom for any of the keys in the queue, then the -- portion of the queue which is bottom is /unspecified/. mapKeysMonotonic :: (k -> k') -> MaxPQueue k a -> MaxPQueue k' a -mapKeysMonotonic f (MaxPQ q) = MaxPQ (Q.mapKeysMonotonic (fmap f) q) +mapKeysMonotonic = coerce Q.mapKeysMonotonic -- | \(O(n \log n)\). Fold the keys and values in the map, such that -- @'foldrWithKey' f z q == 'List.foldr' ('uncurry' f) z ('toDescList' q)@. -- -- If you do not care about the traversal order, consider using 'foldrWithKeyU'. foldrWithKey :: Ord k => (k -> a -> b -> b) -> b -> MaxPQueue k a -> b -foldrWithKey f z (MaxPQ q) = Q.foldrWithKey (f . unDown) z q +foldrWithKey f z (MaxPQ q) = Q.foldrWithKey (coerce f) z q -- | \(O(n \log n)\). Fold the keys and values in the map, such that -- @'foldlWithKey' f z q == 'List.foldl' ('uncurry' . f) z ('toDescList' q)@. -- -- If you do not care about the traversal order, consider using 'foldlWithKeyU'. foldlWithKey :: Ord k => (b -> k -> a -> b) -> b -> MaxPQueue k a -> b -foldlWithKey f z0 (MaxPQ q) = Q.foldlWithKey (\z -> f z . unDown) z0 q +foldlWithKey f z0 (MaxPQ q) = Q.foldlWithKey (coerce f) z0 q -- | \(O(n \log n)\). Traverses the elements of the queue in descending order by key. -- (@'traverseWithKey' f q == 'fromDescList' <$> 'traverse' ('uncurry' f) ('toDescList' q)@) @@ -365,38 +359,26 @@ foldlWithKey f z0 (MaxPQ q) = Q.foldlWithKey (\z -> f z . unDown) z0 q -- -- If you are working in a strict monad, consider using 'mapMWithKey'. traverseWithKey :: (Ord k, Applicative f) => (k -> a -> f b) -> MaxPQueue k a -> f (MaxPQueue k b) -traverseWithKey f (MaxPQ q) = MaxPQ <$> Q.traverseWithKey (f . unDown) q +traverseWithKey f (MaxPQ q) = MaxPQ <$> Q.traverseWithKey (coerce f) q -- | A strictly accumulating version of 'traverseWithKey'. This works well in -- 'IO' and strict @State@, and is likely what you want for other "strict" monads, -- where @⊥ >>= pure () = ⊥@. mapMWithKey :: (Ord k, Monad m) => (k -> a -> m b) -> MaxPQueue k a -> m (MaxPQueue k b) -mapMWithKey f = go empty - where - go !acc q = - case maxViewWithKey q of - Nothing -> pure acc - Just ((k, a), q') -> do - b <- f k a - let !acc' = insertMin' k b acc - go acc' q' - -insertMin' :: k -> a -> MaxPQueue k a -> MaxPQueue k a -insertMin' k a (MaxPQ q) = MaxPQ (PrioInternals.insertMax' (Down k) a q) +mapMWithKey f (MaxPQ q) = MaxPQ <$> Q.mapMWithKey (coerce f) q -- | \(O(k \log n)\). Takes the first @k@ (key, value) pairs in the queue, or the first @n@ if @k >= n@. -- (@'take' k q == 'List.take' k ('toDescList' q)@) take :: Ord k => Int -> MaxPQueue k a -> [(k, a)] -take k (MaxPQ q) = fmap (first' unDown) (Q.take k q) +take = coerce Q.take -- | \(O(k \log n)\). Deletes the first @k@ (key, value) pairs in the queue, or returns an empty queue if @k >= n@. drop :: Ord k => Int -> MaxPQueue k a -> MaxPQueue k a -drop k (MaxPQ q) = MaxPQ (Q.drop k q) +drop = coerce Q.drop -- | \(O(k \log n)\). Equivalent to @('take' k q, 'drop' k q)@. splitAt :: Ord k => Int -> MaxPQueue k a -> ([(k, a)], MaxPQueue k a) -splitAt k (MaxPQ q) = case Q.splitAt k q of - (xs, q') -> (fmap (first' unDown) xs, MaxPQ q') +splitAt = coerce Q.splitAt -- | Takes the longest possible prefix of elements satisfying the predicate. -- (@'takeWhile' p q == 'List.takeWhile' (p . 'snd') ('toDescList' q)@) @@ -406,7 +388,7 @@ takeWhile = takeWhileWithKey . const -- | Takes the longest possible prefix of elements satisfying the predicate. -- (@'takeWhile' p q == 'List.takeWhile' (uncurry p) ('toDescList' q)@) takeWhileWithKey :: Ord k => (k -> a -> Bool) -> MaxPQueue k a -> [(k, a)] -takeWhileWithKey p (MaxPQ q) = fmap (first' unDown) (Q.takeWhileWithKey (p . unDown) q) +takeWhileWithKey = coerce Q.takeWhileWithKey -- | Removes the longest possible prefix of elements satisfying the predicate. dropWhile :: Ord k => (a -> Bool) -> MaxPQueue k a -> MaxPQueue k a @@ -414,7 +396,7 @@ dropWhile = dropWhileWithKey . const -- | Removes the longest possible prefix of elements satisfying the predicate. dropWhileWithKey :: Ord k => (k -> a -> Bool) -> MaxPQueue k a -> MaxPQueue k a -dropWhileWithKey p (MaxPQ q) = MaxPQ (Q.dropWhileWithKey (p . unDown) q) +dropWhileWithKey = coerce Q.dropWhileWithKey -- | Equivalent to @('takeWhile' p q, 'dropWhile' p q)@. span :: Ord k => (a -> Bool) -> MaxPQueue k a -> ([(k, a)], MaxPQueue k a) @@ -426,13 +408,11 @@ break = breakWithKey . const -- | Equivalent to @'spanWithKey' (\k a -> 'not' (p k a)) q@. spanWithKey :: Ord k => (k -> a -> Bool) -> MaxPQueue k a -> ([(k, a)], MaxPQueue k a) -spanWithKey p (MaxPQ q) = case Q.spanWithKey (p . unDown) q of - (xs, q') -> (fmap (first' unDown) xs, MaxPQ q') +spanWithKey = coerce Q.spanWithKey -- | Equivalent to @'spanWithKey' (\k a -> 'not' (p k a)) q@. breakWithKey :: Ord k => (k -> a -> Bool) -> MaxPQueue k a -> ([(k, a)], MaxPQueue k a) -breakWithKey p (MaxPQ q) = case Q.breakWithKey (p . unDown) q of - (xs, q') -> (fmap (first' unDown) xs, MaxPQ q') +breakWithKey = coerce Q.breakWithKey -- | \(O(n)\). Filter all values that satisfy the predicate. filter :: Ord k => (a -> Bool) -> MaxPQueue k a -> MaxPQueue k a @@ -440,7 +420,7 @@ filter = filterWithKey . const -- | \(O(n)\). Filter all values that satisfy the predicate. filterWithKey :: Ord k => (k -> a -> Bool) -> MaxPQueue k a -> MaxPQueue k a -filterWithKey p (MaxPQ q) = MaxPQ (Q.filterWithKey (p . unDown) q) +filterWithKey = coerce Q.filterWithKey -- | \(O(n)\). Partition the queue according to a predicate. The first queue contains all elements -- which satisfy the predicate, the second all elements that fail the predicate. @@ -450,8 +430,7 @@ partition = partitionWithKey . const -- | \(O(n)\). Partition the queue according to a predicate. The first queue contains all elements -- which satisfy the predicate, the second all elements that fail the predicate. partitionWithKey :: Ord k => (k -> a -> Bool) -> MaxPQueue k a -> (MaxPQueue k a, MaxPQueue k a) -partitionWithKey p (MaxPQ q) = case Q.partitionWithKey (p . unDown) q of - (q1, q0) -> (MaxPQ q1, MaxPQ q0) +partitionWithKey = coerce Q.partitionWithKey -- | \(O(n)\). Map values and collect the 'Just' results. mapMaybe :: Ord k => (a -> Maybe b) -> MaxPQueue k a -> MaxPQueue k b @@ -459,7 +438,7 @@ mapMaybe = mapMaybeWithKey . const -- | \(O(n)\). Map values and collect the 'Just' results. mapMaybeWithKey :: Ord k => (k -> a -> Maybe b) -> MaxPQueue k a -> MaxPQueue k b -mapMaybeWithKey f (MaxPQ q) = MaxPQ (Q.mapMaybeWithKey (f . unDown) q) +mapMaybeWithKey = coerce Q.mapMaybeWithKey -- | \(O(n)\). Map values and separate the 'Left' and 'Right' results. mapEither :: Ord k => (a -> Either b c) -> MaxPQueue k a -> (MaxPQueue k b, MaxPQueue k c) @@ -467,20 +446,19 @@ mapEither = mapEitherWithKey . const -- | \(O(n)\). Map values and separate the 'Left' and 'Right' results. mapEitherWithKey :: Ord k => (k -> a -> Either b c) -> MaxPQueue k a -> (MaxPQueue k b, MaxPQueue k c) -mapEitherWithKey f (MaxPQ q) = case Q.mapEitherWithKey (f . unDown) q of - (qL, qR) -> (MaxPQ qL, MaxPQ qR) +mapEitherWithKey = coerce Q.mapEitherWithKey -- | \(O(n)\). Build a priority queue from the list of (key, value) pairs. fromList :: Ord k => [(k, a)] -> MaxPQueue k a -fromList = MaxPQ . Q.fromList . fmap (first' Down) +fromList = coerce Q.fromList -- | \(O(n)\). Build a priority queue from an ascending list of (key, value) pairs. /The precondition is not checked./ fromAscList :: [(k, a)] -> MaxPQueue k a -fromAscList = MaxPQ . Q.fromDescList . fmap (first' Down) +fromAscList = coerce Q.fromDescList -- | \(O(n)\). Build a priority queue from a descending list of (key, value) pairs. /The precondition is not checked./ fromDescList :: [(k, a)] -> MaxPQueue k a -fromDescList = MaxPQ . Q.fromAscList . fmap (first' Down) +fromDescList = coerce Q.fromAscList -- | \(O(n \log n)\). Return all keys of the queue in descending order. keys :: Ord k => MaxPQueue k a -> [k] @@ -496,11 +474,11 @@ assocs = toDescList -- | \(O(n \log n)\). Return all (key, value) pairs in ascending order by key. toAscList :: Ord k => MaxPQueue k a -> [(k, a)] -toAscList (MaxPQ q) = fmap (first' unDown) (Q.toDescList q) +toAscList = coerce Q.toDescList -- | \(O(n \log n)\). Return all (key, value) pairs in descending order by key. toDescList :: Ord k => MaxPQueue k a -> [(k, a)] -toDescList (MaxPQ q) = fmap (first' unDown) (Q.toAscList q) +toDescList = coerce Q.toAscList -- | \(O(n \log n)\). Equivalent to 'toDescList'. -- @@ -514,13 +492,13 @@ foldrU = foldrWithKeyU . const -- | \(O(n)\). An unordered right fold over the elements of the queue, in no particular order. foldrWithKeyU :: (k -> a -> b -> b) -> b -> MaxPQueue k a -> b -foldrWithKeyU f z (MaxPQ q) = Q.foldrWithKeyU (f . unDown) z q +foldrWithKeyU f z (MaxPQ q) = Q.foldrWithKeyU (coerce f) 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 +foldMapWithKeyU f (MaxPQ q) = Q.foldMapWithKeyU (coerce f) 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 @@ -539,13 +517,13 @@ foldlU' f = foldlWithKeyU' (const . f) -- 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 +foldlWithKeyU f z0 (MaxPQ q) = Q.foldlWithKeyU (coerce f) 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 +foldlWithKeyU' f z0 (MaxPQ q) = Q.foldlWithKeyU' (coerce f) z0 q -- | \(O(n)\). An unordered traversal over a priority queue, in no particular order. -- While there is no guarantee in which order the elements are traversed, the resulting @@ -557,7 +535,7 @@ traverseU = traverseWithKeyU . const -- While there is no guarantee in which order the elements are traversed, the resulting -- priority queue will be perfectly valid. traverseWithKeyU :: (Applicative f) => (k -> a -> f b) -> MaxPQueue k a -> f (MaxPQueue k b) -traverseWithKeyU f (MaxPQ q) = MaxPQ <$> Q.traverseWithKeyU (f . unDown) q +traverseWithKeyU f (MaxPQ q) = MaxPQ <$> Q.traverseWithKeyU (coerce f) q -- | \(O(n)\). Return all keys of the queue in no particular order. keysU :: MaxPQueue k a -> [k] @@ -573,7 +551,7 @@ assocsU = toListU -- | \(O(n)\). Returns all (key, value) pairs in the queue in no particular order. toListU :: MaxPQueue k a -> [(k, a)] -toListU (MaxPQ q) = fmap (first' unDown) (Q.toListU q) +toListU = coerce Q.toListU -- | \(O(\log n)\). @seqSpine q r@ forces the spine of @q@ and returns @r@. --