-
Notifications
You must be signed in to change notification settings - Fork 12
Streamline and expand folds #59
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,4 +1,6 @@ | ||
| {-# LANGUAGE CPP, StandaloneDeriving #-} | ||
| {-# LANGUAGE CPP #-} | ||
| {-# LANGUAGE BangPatterns #-} | ||
| {-# LANGUAGE StandaloneDeriving #-} | ||
|
|
||
| module Data.PQueue.Internals ( | ||
| MinQueue (..), | ||
|
|
@@ -34,8 +36,10 @@ module Data.PQueue.Internals ( | |
| fromList, | ||
| mapU, | ||
| fromAscList, | ||
| foldMapU, | ||
| foldrU, | ||
| foldlU, | ||
| foldlU', | ||
| -- traverseU, | ||
| seqSpine, | ||
| unions | ||
|
|
@@ -47,6 +51,7 @@ import Data.Foldable (foldl') | |
| import Data.Semigroup (Semigroup(..), stimesMonoid) | ||
| #endif | ||
|
|
||
| import Data.PQueue.Internals.Foldable | ||
| #ifdef __GLASGOW_HASKELL__ | ||
| import Data.Data | ||
| import Text.Read (Lexeme(Ident), lexP, parens, prec, | ||
|
|
@@ -603,6 +608,63 @@ instance Functor rk => Functor (BinomForest rk) where | |
| fmap f (Skip ts) = Skip (fmap f ts) | ||
| fmap f (Cons t ts) = Cons (fmap f t) (fmap f ts) | ||
|
|
||
| instance Foldr Zero where | ||
| foldr_ _ z ~Zero = z | ||
|
|
||
| instance Foldl Zero where | ||
| foldl_ _ z ~Zero = z | ||
|
|
||
| instance Foldl' Zero where | ||
| foldl'_ _ z ~Zero = z | ||
|
|
||
| instance FoldMap Zero where | ||
| foldMap_ _ ~Zero = mempty | ||
|
|
||
| instance Foldr rk => Foldr (Succ rk) where | ||
| foldr_ f z (Succ t ts) = foldr_ f (foldr_ f z ts) t | ||
|
|
||
| instance Foldl rk => Foldl (Succ rk) where | ||
| foldl_ f z (Succ t ts) = foldl_ f (foldl_ f z t) ts | ||
|
|
||
| instance Foldl' rk => Foldl' (Succ rk) where | ||
| foldl'_ f !z (Succ t ts) = foldl'_ f (foldl'_ f z t) ts | ||
|
|
||
| instance FoldMap rk => FoldMap (Succ rk) where | ||
| foldMap_ f (Succ t ts) = foldMap_ f t `mappend` foldMap_ f ts | ||
|
|
||
| instance Foldr rk => Foldr (BinomTree rk) where | ||
| foldr_ f z (BinomTree x ts) = x `f` foldr_ f z ts | ||
|
|
||
| instance Foldl rk => Foldl (BinomTree rk) where | ||
| foldl_ f z (BinomTree x ts) = foldl_ f (z `f` x) ts | ||
|
|
||
| instance Foldl' rk => Foldl' (BinomTree rk) where | ||
| foldl'_ f !z (BinomTree x ts) = foldl'_ f (z `f` x) ts | ||
|
|
||
| instance FoldMap rk => FoldMap (BinomTree rk) where | ||
| foldMap_ f (BinomTree x ts) = f x `mappend` foldMap_ f ts | ||
|
|
||
| instance Foldr rk => Foldr (BinomForest rk) where | ||
| foldr_ _ z Nil = z | ||
| foldr_ f z (Skip tss) = foldr_ f z tss | ||
| foldr_ f z (Cons t tss) = foldr_ f (foldr_ f z tss) t | ||
|
|
||
| instance Foldl rk => Foldl (BinomForest rk) where | ||
| foldl_ _ z Nil = z | ||
| foldl_ f z (Skip tss) = foldl_ f z tss | ||
| foldl_ f z (Cons t tss) = foldl_ f (foldl_ f z t) tss | ||
|
|
||
| instance Foldl' rk => Foldl' (BinomForest rk) where | ||
| foldl'_ _ !z Nil = z | ||
| foldl'_ f !z (Skip tss) = foldl'_ f z tss | ||
| foldl'_ f !z (Cons t tss) = foldl'_ f (foldl'_ f z t) tss | ||
|
|
||
| instance FoldMap rk => FoldMap (BinomForest rk) where | ||
| foldMap_ _ Nil = mempty | ||
| foldMap_ f (Skip tss) = foldMap_ f tss | ||
| foldMap_ f (Cons t tss) = foldMap_ f t `mappend` foldMap_ f tss | ||
|
|
||
| {- | ||
| instance Foldable Zero where | ||
| foldr _ z ~Zero = z | ||
| foldl _ z ~Zero = z | ||
|
|
@@ -622,6 +684,7 @@ instance Foldable rk => Foldable (BinomForest rk) where | |
| foldl _ z Nil = z | ||
| foldl f z (Skip tss) = foldl f z tss | ||
| foldl f z (Cons t tss) = foldl f (foldl f z t) tss | ||
| -} | ||
|
|
||
| -- instance Traversable Zero where | ||
| -- traverse _ _ = pure Zero | ||
|
|
@@ -645,12 +708,28 @@ mapU f (MinQueue n x ts) = MinQueue n (f x) (f <$> ts) | |
| -- | /O(n)/. Unordered right fold on a priority queue. | ||
| foldrU :: (a -> b -> b) -> b -> MinQueue a -> b | ||
| foldrU _ z Empty = z | ||
| foldrU f z (MinQueue _ x ts) = x `f` foldr f z ts | ||
| foldrU f z (MinQueue _ x ts) = x `f` foldr_ f z ts | ||
|
|
||
| -- | /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. | ||
|
treeowl marked this conversation as resolved.
|
||
| foldlU :: (b -> a -> b) -> b -> MinQueue a -> b | ||
| foldlU _ z Empty = z | ||
| foldlU f z (MinQueue _ x ts) = foldl f (z `f` x) ts | ||
| foldlU f z (MinQueue _ x ts) = foldl_ f (z `f` x) ts | ||
|
|
||
| -- | /O(n)/. Unordered strict left fold on a priority queue. | ||
| -- | ||
| -- @since 1.4.2 | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This seems to be the only file you added
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, you're right. I'll have to fix that up. |
||
| foldlU' :: (b -> a -> b) -> b -> MinQueue a -> b | ||
| foldlU' _ z Empty = z | ||
| foldlU' f z (MinQueue _ x ts) = foldl'_ f (z `f` x) ts | ||
|
|
||
| -- | /O(n)/. Unordered monoidal fold on a priority queue. | ||
| -- | ||
| -- @since 1.4.2 | ||
| foldMapU :: Monoid m => (a -> m) -> MinQueue a -> m | ||
| foldMapU _ Empty = mempty | ||
| foldMapU f (MinQueue _ x ts) = f x `mappend` foldMap_ f ts | ||
|
|
||
| {-# NOINLINE toListU #-} | ||
| -- | /O(n)/. Returns the elements of the queue, in no particular order. | ||
|
|
@@ -660,7 +739,7 @@ toListU q = foldrU (:) [] q | |
| {-# NOINLINE toListUApp #-} | ||
| toListUApp :: MinQueue a -> [a] -> [a] | ||
| toListUApp Empty app = app | ||
| toListUApp (MinQueue _ x ts) app = x : foldr (:) app ts | ||
| toListUApp (MinQueue _ x ts) app = x : foldr_ (:) app ts | ||
|
|
||
| {-# RULES | ||
| "toListU/build" [~1] forall q. toListU q = build (\c n -> foldrU c n q) | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,38 @@ | ||
| -- | Writing 'Foldable' instances for non-regular (AKA, nested) types in the | ||
| -- natural manner leads to full `Foldable` dictionaries being constructed on | ||
| -- each recursive call. This is pretty inefficient. It's better to construct | ||
| -- exactly what we need instead. | ||
| module Data.PQueue.Internals.Foldable | ||
| ( Foldr (..) | ||
| , Foldl (..) | ||
| , FoldMap (..) | ||
| , Foldl' (..) | ||
| , IFoldr (..) | ||
| , IFoldl (..) | ||
| , IFoldMap (..) | ||
| , IFoldl' (..) | ||
| ) where | ||
|
|
||
| class Foldr t where | ||
| foldr_ :: (a -> b -> b) -> b -> t a -> b | ||
|
|
||
| class IFoldr t where | ||
| foldrWithKey_ :: (k -> a -> b -> b) -> b -> t k a -> b | ||
|
|
||
| class Foldl t where | ||
| foldl_ :: (b -> a -> b) -> b -> t a -> b | ||
|
|
||
| class IFoldl t where | ||
| foldlWithKey_ :: (b -> k -> a -> b) -> b -> t k a -> b | ||
|
|
||
| class FoldMap t where | ||
| foldMap_ :: Monoid m => (a -> m) -> t a -> m | ||
|
|
||
| class IFoldMap t where | ||
| foldMapWithKey_ :: Monoid m => (k -> a -> m) -> t k a -> m | ||
|
|
||
| class Foldl' t where | ||
| foldl'_ :: (b -> a -> b) -> b -> t a -> b | ||
|
|
||
| class IFoldl' t where | ||
| foldlWithKey'_ :: (b -> k -> a -> b) -> b -> t k a -> b |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -74,6 +74,8 @@ module Data.PQueue.Max ( | |
| mapU, | ||
| foldrU, | ||
| foldlU, | ||
| foldlU', | ||
| foldMapU, | ||
| elemsU, | ||
| toListU, | ||
| -- * Miscellaneous operations | ||
|
|
@@ -88,6 +90,8 @@ import Data.Maybe (fromMaybe) | |
| import Data.Semigroup (Semigroup(..), stimesMonoid) | ||
| #endif | ||
|
|
||
| import Data.Foldable (foldl') | ||
|
|
||
| import qualified Data.PQueue.Min as Min | ||
| import qualified Data.PQueue.Prio.Max.Internals as Prio | ||
| import Data.PQueue.Internals.Down (Down(..)) | ||
|
|
@@ -273,10 +277,18 @@ mapU f (MaxQ q) = MaxQ (Min.mapU (\(Down a) -> Down (f a)) q) | |
| 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. | ||
| 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. | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. You forgot the note about performance. |
||
| 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. | ||
| foldlU' :: (b -> a -> b) -> b -> MaxQueue a -> b | ||
| foldlU' f z (MaxQ q) = Min.foldlU' (foldl' f) z q | ||
|
|
||
| {-# INLINE elemsU #-} | ||
| -- | Equivalent to 'toListU'. | ||
| elemsU :: MaxQueue a -> [a] | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.