pqueue 1.0.0 → 1.0.1
raw patch · 7 files changed
+358/−155 lines, 7 files
Files
- Data/PQueue/Internals.hs +5/−7
- Data/PQueue/Max.hs +247/−118
- Data/PQueue/Min.hs +28/−5
- Data/PQueue/Prio/Max.hs +30/−22
- Data/PQueue/Prio/Max/Internals.hs +41/−0
- Data/PQueue/Prio/Min.hs +5/−2
- pqueue.cabal +2/−1
Data/PQueue/Internals.hs view
@@ -39,13 +39,7 @@ import Prelude hiding (foldl, foldr, null) --- | A priority queue implementation. Implemented as a find-min wrapper around a binomial heap.--- --- If you wish to perform folds on a priority queue that respect order, use 'foldrAsc' or--- 'foldlAsc'.--- --- For any operation @op@ in 'Eq' or 'Ord', @queue1 `op` queue2@ is equivalent to--- @toAscList queue1 `op` toAscList queue2@.+-- | A priority queue with elements of type @a@. Supports extracting the minimum element. data MinQueue a = Empty | MinQueue {-# UNPACK #-} !Int a !(BinomHeap a) #ifdef __GLASGOW_HASKELL__@@ -168,10 +162,13 @@ size Empty = 0 size (MinQueue n _ _) = n +-- | Returns the minimum element of the queue, if the queue is nonempty. getMin :: MinQueue a -> Maybe a getMin (MinQueue _ x _) = Just x getMin _ = Nothing +-- | Retrieves the minimum element of the queue, and the queue stripped of that element, +-- or 'Nothing' if passed an empty queue. minView :: Ord a => MinQueue a -> Maybe (a, MinQueue a) minView Empty = Nothing minView (MinQueue n x ts) = Just (x, case extractHeap ts of@@ -427,6 +424,7 @@ foldrU _ z Empty = z foldrU f z (MinQueue _ x ts) = x `f` foldr f z ts +-- | /O(n)/. Unordered left fold on a priority queue. foldlU :: (b -> a -> b) -> b -> MinQueue a -> b foldlU _ z Empty = z foldlU f z (MinQueue _ x ts) = foldl f (z `f` x) ts
Data/PQueue/Max.hs view
@@ -1,33 +1,50 @@ {-# LANGUAGE CPP #-} +-----------------------------------------------------------------------------+-- |+-- Module : Data.PQueue.Min+-- Copyright : (c) Louis Wasserman 2010+-- License : BSD-style+-- Maintainer : libraries@haskell.org+-- Stability : experimental+-- Portability : portable+--+-- General purpose priority queue, supporting maxView-maximum operations.+--+-- An amortized running time is given for each operation, with /n/ referring+-- to the length of the sequence and /i/ being the integral index used by+-- some operations. These bounds hold even in a persistent (shared) setting.+--+-- This implementation is based on a binomial heap augmented with a global root.+-- The spine of the heap is maintained lazily. To force the spine of the heap,+-- use 'seqSpine'.+--+-- This implementation does not guarantee stable behavior.+-- +-- This implementation offers a number of methods of the form @xxxU@, where @U@ stands for+-- unordered. No guarantees whatsoever are made on the execution or traversal order of+-- these functions.+----------------------------------------------------------------------------- module Data.PQueue.Max ( MaxQueue,- -- * Construction+ -- * Basic operations empty,- singleton,- insert,- union,- unions,- -- * Query null,- size,- -- ** Maximum view+ size, + -- * Query operations findMax, getMax, deleteMax, deleteFindMax, maxView,- -- * Traversal- -- ** Map- map,- mapMonotonic,- -- ** Fold- foldr,- foldl,- -- ** Traverse- traverse,+ -- * Construction operations+ singleton,+ insert,+ union,+ unions, -- * Subsets- -- ** Indexed+ -- ** Extracting subsets+ (!!), take, drop, splitAt,@@ -36,35 +53,49 @@ dropWhile, span, break,- -- *** Filter+ -- * Filter/Map filter, partition,+ mapMaybe,+ mapEither,+ -- * Fold\/Functor\/Traversable variations+ map,+ foldrAsc,+ foldlAsc,+ foldrDesc,+ foldlDesc, -- * List operations- -- ** Conversion from lists- fromList,- fromDescList,- fromAscList,- -- ** Conversion to lists- elems, toList,+ toAscList, toDescList,- -- * Conversion with MaxPQueue- pqueueKeys,+ fromList,+ fromAscList,+ fromDescList, -- * Unordered operations+ mapU, foldrU, foldlU,+ traverseU,+ elemsU, toListU,- -- * Helper methods+ -- * Miscellaneous operations+ keysQueue, seqSpine) where -import Control.Applicative hiding (empty)-import Data.Maybe hiding (mapMaybe)+import Control.Applicative (Applicative(..), (<$>))+ import Data.Monoid-import qualified Data.List as List-import qualified Data.PQueue.Prio.Max as Q+import Data.Maybe hiding (mapMaybe)+import Data.Foldable hiding (toList)+import Data.Traversable+import Data.Ord -import Prelude hiding (map, filter, break, span, takeWhile, dropWhile, splitAt, take, drop, (!!), null, foldr, foldl)+import qualified Data.PQueue.Min as Min+import qualified Data.PQueue.Prio.Max.Internals as Prio+import Data.PQueue.Prio.Max.Internals (Down(..)) +import Prelude hiding (null, foldr, foldl, take, drop, takeWhile, dropWhile, splitAt, span, break, (!!), filter)+ #ifdef __GLASGOW_HASKELL__ import GHC.Exts (build) import Text.Read (Lexeme(Ident), lexP, parens, prec,@@ -75,143 +106,241 @@ build f = f (:) [] #endif -newtype MaxQueue a = MaxQ (Q.MaxPQueue a ()) deriving (Eq, Ord)--null :: MaxQueue a -> Bool-null (MaxQ q) = Q.null q+-- | A priority queue implementation. Implemented as a wrapper around "Data.PQueue.Min". +-- /Warning/: the 'Functor', 'Foldable', and 'Traversable' instances of this type /ignore ordering/.+-- For 'Functor', it is guaranteed that if @f@ is a monotonic function, then @'fmap' f@ on a valid+-- 'MaxQueue' will return a valid 'MaxQueue'. An analogous guarantee holds for 'traverse'. (Note:+-- if passed constant-time operations, every function in 'Functor', 'Foldable', and 'Traversable'+-- will run in /O(n)/.)+-- +-- If you wish to perform folds on a priority queue that respect order, use 'foldrDesc' or+-- 'foldlDesc'.+newtype MaxQueue a = MaxQ (Min.MinQueue (Down a))+# if __GLASGOW_HASKELL__+ deriving (Eq, Ord, Data, Typeable)+# else+ deriving (Eq, Ord)+# endif -size :: MaxQueue a -> Int-size (MaxQ q) = Q.size q+instance (Ord a, Show a) => Show (MaxQueue a) where+ showsPrec p xs = showParen (p > 10) $+ showString "fromDescList " . shows (toDescList xs)+ +instance Read a => Read (MaxQueue a) where+#ifdef __GLASGOW_HASKELL__+ readPrec = parens $ prec 10 $ do+ Ident "fromDescList" <- lexP+ xs <- readPrec+ return (fromDescList xs) -empty :: MaxQueue a-empty = MaxQ Q.empty+ readListPrec = readListPrecDefault+#else+ readsPrec p = readParen (p > 10) $ \ r -> do+ ("fromDescList",s) <- lex r+ (xs,t) <- reads s+ return (fromDescList xs,t)+#endif -singleton :: a -> MaxQueue a-singleton a = MaxQ (Q.singleton a ())+instance Ord a => Monoid (MaxQueue a) where+ mempty = empty+ mappend = union -insert :: Ord a => a -> MaxQueue a -> MaxQueue a-insert a (MaxQ q) = MaxQ (Q.insert a () q)+-- | /O(1)/. The empty priority queue.+empty :: MaxQueue a+empty = MaxQ Min.empty -union :: Ord a => MaxQueue a -> MaxQueue a -> MaxQueue a-MaxQ q1 `union` MaxQ q2 = MaxQ (q1 `Q.union` q2)+-- | /O(1)/. Is this the empty priority queue?+null :: MaxQueue a -> Bool+null (MaxQ q) = Min.null q -unions :: Ord a => [MaxQueue a] -> MaxQueue a-unions qs = MaxQ (Q.unions [q | MaxQ q <- qs])+-- | /O(1)/. The number of elements in the queue.+size :: MaxQueue a -> Int+size (MaxQ q) = Min.size q +-- | /O(1)/. Returns the maximum element of the queue. Throws an error on an empty queue. findMax :: MaxQueue a -> a-findMax = fromMaybe (error "Error: findMax called on an empty queue") . getMax+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) = fst <$> Q.getMax q+getMax (MaxQ q) = unDown <$> Min.getMin q +-- | /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 (Q.deleteMax q)+deleteMax (MaxQ q) = MaxQ (Min.deleteMin q) +-- | /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)-deleteFindMax = fromMaybe (error "Error: deleteFindMax called on an empty queue") . maxView+deleteFindMax = fromMaybe (error "Error: deleteFindMax called on empty queue") . maxView +-- | /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) = do- ((a, _), q') <- Q.maxViewWithKey q- return (a, MaxQ q')--map :: Ord b => (a -> b) -> MaxQueue a -> MaxQueue b-map f (MaxQ q) = MaxQ (Q.mapKeys f q)--mapMonotonic :: (a -> b) -> MaxQueue a -> MaxQueue b-mapMonotonic f (MaxQ q) = MaxQ (Q.mapKeysMonotonic f q)+maxView (MaxQ q) = case Min.minView q of+ Nothing -> Nothing+ Just (Down x, q')+ -> Just (x, MaxQ q')+ +-- | /O(log n)/. Delete the top (maximum) element of the sequence, if there is one.+delete :: Ord a => MaxQueue a -> Maybe (MaxQueue a)+delete = fmap snd . maxView -traverse :: (Applicative f, Ord a, Ord b) => (a -> f b) -> MaxQueue a -> f (MaxQueue b)-traverse f q = case maxView q of- Nothing -> pure empty- Just (a, q') -> insert <$> f a <*> traverse f q'+-- | /O(1)/. Construct a priority queue with a single element.+singleton :: a -> MaxQueue a+singleton = MaxQ . Min.singleton . Down -foldr :: Ord a => (a -> b -> b) -> b -> MaxQueue a -> b-foldr f z (MaxQ q) = Q.foldrWithKey (const . f) z q+-- | /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) -foldl :: Ord a => (b -> a -> b) -> b -> MaxQueue a -> b-foldl f z (MaxQ q) = Q.foldlWithKey (\ z -> const . f z) z q+-- | /O(log (min(n1,n2)))/. Take the union of two priority queues.+union :: Ord a => MaxQueue a -> MaxQueue a -> MaxQueue a+MaxQ q1 `union` MaxQ q2 = MaxQ (q1 `Min.union` q2) -foldrU :: (a -> b -> b) -> b -> MaxQueue a -> b-foldrU f z (MaxQ q) = Q.foldrWithKeyU (const . f) z q+-- | 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]) -foldlU :: (b -> a -> b) -> b -> MaxQueue a -> b-foldlU f z (MaxQ q) = Q.foldlWithKeyU (\ z -> const . f z) z q+-- | /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) --- {-# INLINE take #-}+{-# 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) = List.map fst (Q.take k q)+take k (MaxQ q) = [a | Down a <- Min.take k q] +-- | /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 (Q.drop k q)+drop k (MaxQ q) = MaxQ (Min.drop k q) +-- | /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) = case Q.splitAt k q of- (xs, q') -> (List.map fst xs, MaxQ q')-+splitAt k (MaxQ q) = (map unDown xs, MaxQ q') where+ (xs, q') = Min.splitAt k q+ +-- | '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) = List.map fst (Q.takeWhileWithKey (const . p) q)+takeWhile p (MaxQ q) = map unDown (Min.takeWhile (p . unDown) q) +-- | '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 (Q.dropWhileWithKey (const . p) q)+dropWhile p (MaxQ q) = MaxQ (Min.dropWhile (p . unDown) q) +-- | '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) = case Q.spanWithKey (const . p) q of- (xs, q') -> (List.map fst xs, MaxQ q')+span p (MaxQ q) = (map unDown xs, MaxQ q') where+ (xs, q') = Min.span (p . unDown) q +-- | '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+-- /do not satisfy/ @p@ and second element is the remainder of the queue. break :: Ord a => (a -> Bool) -> MaxQueue a -> ([a], MaxQueue a)-break p (MaxQ q) = case Q.breakWithKey (const . p) q of- (xs, q') -> (List.map fst xs, MaxQ q')+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 f (MaxQ q) = MaxQ (Q.filterWithKey (const . f) q)+filter p (MaxQ q) = MaxQ (Min.filter (p . unDown) q) +-- | /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) = case Q.partitionWithKey (const . p) q of- (q0, q1) -> (MaxQ q0, MaxQ q1)+partition p (MaxQ q) = (MaxQ q0, MaxQ q1)+ where (q0, q1) = Min.partition (p . unDown) q -{-# INLINE elems #-}-elems :: Ord a => MaxQueue a -> [a]-elems = toList+-- | /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) -{-# INLINE toList #-}-toList :: Ord a => MaxQueue a -> [a]-toList (MaxQ q) = Q.keys q+-- | /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 -{-# INLINE toDescList #-}-toDescList :: Ord a => MaxQueue a -> [a]-toDescList = toList+-- | /O(n)/. Assumes that the function it is given is monotonic, and applies this function to every element of the priority queue.+-- /Does not check the precondition/.+mapU :: (a -> b) -> MaxQueue a -> MaxQueue b+mapU f (MaxQ q) = MaxQ (Min.mapU (\ (Down a) -> Down (f a)) q) -{-# INLINE toAscList #-}-toAscList :: Ord a => MaxQueue a -> [a]-toAscList (MaxQ q) = List.map fst (Q.toAscList q)+-- | /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 +-- | /O(n)/. Unordered left fold on a priority queue.+foldlU :: (b -> a -> b) -> b -> MaxQueue a -> b+foldlU f z (MaxQ q) = Min.foldlU (foldl f) z q+ {-# INLINE elemsU #-}-elemsU :: Ord a => MaxQueue a -> [a]+-- | Equivalent to 'toListU'.+elemsU :: MaxQueue a -> [a] elemsU = toListU {-# INLINE toListU #-}-toListU :: Ord a => MaxQueue a -> [a]-toListU (MaxQ q) = Q.keysU q+-- | /O(n)/. Returns a list of the elements of the priority queue, in no particular order.+toListU :: MaxQueue a -> [a]+toListU (MaxQ q) = map unDown (Min.toListU q) -{-# INLINE fromList #-}-fromList :: Ord a => [a] -> MaxQueue a-fromList as = MaxQ (Q.fromList [(a, ()) | a <- as])+-- | /O(n)/. Assumes that the function it is given is monotonic, in some sense, and performs the 'traverse' operation.+-- If the function is not monotonic, the result is undefined.+traverseU :: (Applicative f, Ord b) => (a -> f b) -> MaxQueue a -> f (MaxQueue b)+traverseU f (MaxQ q) = MaxQ <$> Min.traverseU (traverse f) q -{-# INLINE fromDescList #-}-fromDescList :: [a] -> MaxQueue a-fromDescList as = MaxQ (Q.fromDescList [(a, ()) | a <- as])+-- | /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@.+foldrAsc :: Ord a => (a -> b -> b) -> b -> MaxQueue a -> b+foldrAsc = foldlDesc . flip +-- | /O(n log n)/. Performs a left-fold on the elements of a priority queue in descending order.+-- @'foldlAsc' f z q == 'foldrDesc' (flip f) z q@.+foldlAsc :: Ord a => (b -> a -> b) -> b -> MaxQueue a -> b+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++-- | /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++{-# INLINE toAscList #-}+-- | /O(n log n)/. Extracts the elements of the priority queue in ascending order.+toAscList :: Ord a => MaxQueue a -> [a]+toAscList q = build (\ c nil -> foldrAsc c nil q)++{-# INLINE toDescList #-}+-- | /O(n log n)/. Extracts the elements of the priority queue in descending order.+toDescList :: Ord a => MaxQueue a -> [a]+toDescList q = build (\ c nil -> foldrDesc c nil q)++{-# INLINE toList #-}+-- | /O(n)/. Returns the elements of the priority queue in no particular order.+toList :: Ord a => MaxQueue a -> [a]+toList (MaxQ q) = map unDown (Min.toList q)+ {-# INLINE fromAscList #-}+-- | /O(n)/. Constructs a priority queue from an ascending list. /Warning/: Does not check the precondition. fromAscList :: [a] -> MaxQueue a-fromAscList as = MaxQ (Q.fromAscList [(a, ()) | a <- as])+fromAscList = MaxQ . Min.fromDescList . map Down -pqueueKeys :: Q.MaxPQueue k a -> MaxQueue k-#ifdef __GLASGOW_HASKELL__-pqueueKeys q = MaxQ (() <$ q)-#else-pqueueKeys q = MaxQ (fmap (const ()) q)-#endif+{-# 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 . map Down +{-# INLINE fromList #-}+-- | /O(n log n)/. Constructs a priority queue from an unordered list.+fromList :: Ord a => [a] -> MaxQueue a+fromList = foldr insert empty++-- | /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)++-- | /O(log n)/. Forces the spine of the heap. seqSpine :: MaxQueue a -> b -> b-seqSpine (MaxQ q) = Q.seqSpine q+seqSpine (MaxQ q) = Min.seqSpine q
Data/PQueue/Min.hs view
@@ -16,13 +16,14 @@ -- some operations. These bounds hold even in a persistent (shared) setting. -- -- This implementation is based on a binomial heap augmented with a global root.--- The spine of the heap is maintained strictly, ensuring that computations happen--- as they are performed.+-- The spine of the heap is maintained lazily. To force the spine of the heap,+-- use 'seqSpine'. -- -- This implementation does not guarantee stable behavior. -- --- /WARNING:/ 'toList' and 'toAscList' are /not/ equivalent, unlike for example--- "Data.Map".+-- This implementation offers a number of methods of the form @xxxU@, where @U@ stands for+-- unordered. No guarantees whatsoever are made on the execution or traversal order of+-- these functions. ----------------------------------------------------------------------------- module Data.PQueue.Min ( MinQueue,@@ -59,11 +60,12 @@ mapEither, -- * Fold\/Functor\/Traversable variations map,- mapMonotonic, foldrAsc, foldlAsc, foldrDesc, foldlDesc,+ traverseAsc,+ traverseDesc, -- * List operations toList, toAscList,@@ -72,6 +74,7 @@ fromAscList, fromDescList, -- * Unordered operations+ mapU, foldrU, foldlU, traverseU,@@ -130,14 +133,17 @@ mappend = union mconcat = unions +-- | /O(1)/. Returns the minimum element. Throws an error on an empty queue. findMin :: MinQueue a -> a findMin = fromMaybe (error "Error: findMin called on empty queue") . getMin +-- | /O(log n)/. Deletes the minimum element. If the queue is empty, does nothing. deleteMin :: Ord a => MinQueue a -> MinQueue a deleteMin q = case minView q of Nothing -> empty Just (_, q') -> q' +-- | /O(log n)/. Extracts the minimum element. Throws an error on an empty queue. deleteFindMin :: Ord a => MinQueue a -> (a, MinQueue a) deleteFindMin = fromMaybe (error "Error: deleteFindMin called on empty queue") . minView @@ -258,6 +264,14 @@ foldlDesc :: Ord a => (b -> a -> b) -> b -> MinQueue a -> b foldlDesc = foldrAsc . flip +-- | /O(n log n)/. Equivalent to @'fromList' <$> 'traverse' f ('toAscList' q)@.+traverseAsc :: (Applicative f, Ord a, Ord b) => (a -> f b) -> MinQueue a -> f (MinQueue b)+traverseAsc f = foldrAsc (\ a q -> insert <$> f a <*> q) (pure empty)++-- | /O(n log n)/. Equivalent to @'fromList' <$> 'traverse' f ('toDescList' q)@.+traverseDesc :: (Applicative f, Ord a, Ord b) => (a -> f b) -> MinQueue a -> f (MinQueue b)+traverseDesc f = foldrDesc (\ a q -> insert <$> f a <*> q) (pure empty)+ {-# INLINE fromList #-} -- | /O(n)/. Constructs a priority queue from an unordered list. fromList :: Ord a => [a] -> MinQueue a@@ -277,13 +291,22 @@ fromDescList :: [a] -> MinQueue a fromDescList = foldl' (flip insertMinQ) empty +-- | Maps a function over the elements of the queue, ignoring order. This function is only safe if the function is monotonic.+-- This function /does not/ check the precondition.+mapU :: (a -> b) -> MinQueue a -> MinQueue b+mapU = mapMonotonic+ {-# INLINE elemsU #-}+-- | Equivalent to 'toListU'. elemsU :: MinQueue a -> [a] elemsU = toListU +-- | Returns the elements of the queue, in no particular order. toListU :: MinQueue a -> [a] toListU q = build (\ c n -> foldrU c n q) +-- | /O(n)/. Iterates over the elements of the queue in no particular order, but returns a valid queue that+-- respects the order of the returned elements. traverseU :: (Applicative f, Ord b) => (a -> f b) -> MinQueue a -> f (MinQueue b) traverseU f = foldrU (\ a q -> insert <$> f a <*> q) (pure empty)
Data/PQueue/Prio/Max.hs view
@@ -9,24 +9,25 @@ -- Stability : experimental -- Portability : portable ----- General purpose priority queue, supporting extract-minimum operations.+-- General purpose priority queue. -- Each element is associated with a /key/, and the priority queue supports--- viewing and extracting the element with the minimum key.+-- viewing and extracting the element with the maximum key. ----- An amortized running time is given for each operation, with /n/ referring--- to the length of the sequence and /i/ being the integral index used by--- some operations. These bounds hold even in a persistent (shared) setting.+-- A worst-case bound is given for each operation. In some cases, an amortized+-- bound is also specified; these bounds do not hold in a persistent context. -- -- This implementation is based on a binomial heap augmented with a global root.--- The spine of the heap is maintained lazily.------ This implementation does not guarantee stable behavior. Ties are broken--- arbitrarily -- that is, if @k1 <= k2@ and @k2 <= k1@, then there are no--- guarantees about the relative order in which @k1@, @k2@, and their associated--- elements are returned.+-- The spine of the heap is maintained lazily. To force the spine of the heap,+-- use 'seqSpine'. -- +-- We do not guarantee stable behavior.+-- Ties are broken arbitrarily -- that is, if @k1 <= k2@ and @k2 <= k1@, then there +-- are no guarantees about the relative order in which @k1@, @k2@, and their associated+-- elements are returned. (Unlike Data.Map, we allow multiple elements with the+-- same key.)+-- -- This implementation offers a number of methods of the form @xxxU@, where @U@ stands for--- "unordered." No guarantees are made on the execution or traversal order of+-- unordered. No guarantees whatsoever are made on the execution or traversal order of -- these functions. ----------------------------------------------------------------------------- module Data.PQueue.Prio.Max (@@ -120,6 +121,7 @@ import Data.Foldable hiding (toList) import Data.Traversable import Data.Maybe hiding (mapMaybe)+import Data.PQueue.Prio.Max.Internals import Prelude hiding (map, filter, break, span, takeWhile, dropWhile, splitAt, take, drop, (!!), null, foldr, foldl) @@ -141,18 +143,24 @@ second' :: (b -> c) -> (a, b) -> (a, c) second' f (a, b) = (a, f b) -newtype Down a = Down {unDown :: a} deriving (Eq)---- | A priority queue where values of type @a@ are annotated with keys of type @k@.--- The queue supports extracting the element with maximum key.-newtype MaxPQueue k a = MaxPQ (Q.MinPQueue (Down k) a) deriving (Eq, Ord)+instance (Ord k, Show k, Show a) => Show (MaxPQueue k a) where+ showsPrec p xs = showParen (p > 10) $+ showString "fromDescList " . shows (toDescList xs) -instance Ord a => Ord (Down a) where- Down a `compare` Down b = b `compare` a- Down a <= Down b = b <= a+instance (Read k, Read a) => Read (MaxPQueue k a) where+#ifdef __GLASGOW_HASKELL__+ readPrec = parens $ prec 10 $ do+ Ident "fromDescList" <- lexP+ xs <- readPrec+ return (fromDescList xs) -instance Functor Down where- fmap f (Down a) = Down (f a)+ readListPrec = readListPrecDefault+#else+ readsPrec p = readParen (p > 10) $ \ r -> do+ ("fromDescList",s) <- lex r+ (xs,t) <- reads s+ return (fromDescList xs,t)+#endif instance Functor (MaxPQueue k) where fmap f (MaxPQ q) = MaxPQ (fmap f q)
+ Data/PQueue/Prio/Max/Internals.hs view
@@ -0,0 +1,41 @@+{-# LANGUAGE CPP #-}++module Data.PQueue.Prio.Max.Internals where++import Control.Applicative++import Data.Foldable+import Data.Traversable+# if __GLASGOW_HASKELL__+import Data.Data+# endif++import Prelude hiding (foldr, foldl)++import Data.PQueue.Prio.Internals (MinPQueue)++newtype Down a = Down {unDown :: a} +# if __GLASGOW_HASKELL__+ deriving (Eq, Data, Typeable)+# else+ deriving (Eq)+# endif++-- | A priority queue where values of type @a@ are annotated with keys of type @k@.+-- The queue supports extracting the element with maximum key.+newtype MaxPQueue k a = MaxPQ (MinPQueue (Down k) a) deriving (Eq, Ord)++instance Ord a => Ord (Down a) where+ Down a `compare` Down b = b `compare` a+ Down a <= Down b = b <= a++instance Functor Down where+ fmap f (Down a) = Down (f a)+++instance Foldable Down where+ foldr f z (Down a) = a `f` z+ foldl f z (Down a) = z `f` a++instance Traversable Down where+ traverse f (Down a) = Down <$> f a
Data/PQueue/Prio/Min.hs view
@@ -17,10 +17,13 @@ -- bound is also specified; these bounds do not hold in a persistent context. -- -- This implementation is based on a binomial heap augmented with a global root.--- The spine of the heap is maintained lazily. We do not guarantee stable behavior.+-- The spine of the heap is maintained lazily. To force the spine of the heap,+-- use 'seqSpine'.+-- +-- We do not guarantee stable behavior. -- Ties are broken arbitrarily -- that is, if @k1 <= k2@ and @k2 <= k1@, then there -- are no guarantees about the relative order in which @k1@, @k2@, and their associated--- elements are returned. (Unlike "Data.Map", we allow multiple elements with the+-- elements are returned. (Unlike Data.Map, we allow multiple elements with the -- same key.) -- -- This implementation offers a number of methods of the form @xxxU@, where @U@ stands for
pqueue.cabal view
@@ -1,5 +1,5 @@ Name: pqueue-Version: 1.0.0+Version: 1.0.1 Category: Data Structures Author: Louis Wasserman License: BSD3@@ -26,6 +26,7 @@ other-modules: Data.PQueue.Prio.Internals Data.PQueue.Internals+ Data.PQueue.Prio.Max.Internals if impl(ghc) { extensions: DeriveDataTypeable