diff --git a/Data/Set/Internal.hs b/Data/Set/Internal.hs index a6ee13ca1..598b9fc07 100644 --- a/Data/Set/Internal.hs +++ b/Data/Set/Internal.hs @@ -940,6 +940,18 @@ foldlFB :: (a -> b -> a) -> a -> Set b -> a foldlFB = foldl {-# INLINE[0] foldlFB #-} +-- Used for write-back. Thanks to GHC Trac #16261, we can't actually match on [] in +-- RULES. We actually get a bit more write-back this way: toAscList s ++ l will +-- become toAscListThen s l. We NOINLINE these functions because it seems extremely +-- unlikely that inlining them will ever be helpful in practice, and bloating code is bad. +toAscListThen :: Set a -> [a] -> [a] +toAscListThen s l = foldr (:) l s +{-# NOINLINE toAscListThen #-} + +toDescListThen :: Set a -> [a] -> [a] +toDescListThen s l = foldl (flip (:)) l s +{-# NOINLINE toDescListThen #-} + -- Inline elems and toList, so that we need to fuse only toAscList. {-# INLINE elems #-} {-# INLINE toList #-} @@ -947,15 +959,15 @@ foldlFB = foldl -- The fusion is enabled up to phase 2 included. If it does not succeed, -- convert in phase 1 the expanded to{Asc,Desc}List calls back to -- to{Asc,Desc}List. In phase 0, we inline fold{lr}FB (which were used in --- a list fusion, otherwise it would go away in phase 1), and let compiler do --- whatever it wants with to{Asc,Desc}List -- it was forbidden to inline it --- before phase 0, otherwise the fusion rules would not fire at all. -{-# NOINLINE[0] toAscList #-} -{-# NOINLINE[0] toDescList #-} +-- a list fusion, otherwise it would go away in phase 1). We NOINLINE +-- toAscList and toDescList in all phases because it seems pretty unlikely +-- that inlining them will ever help anyone. +{-# NOINLINE toAscList #-} +{-# NOINLINE toDescList #-} {-# RULES "Set.toAscList" [~1] forall s . toAscList s = build (\c n -> foldrFB c n s) #-} -{-# RULES "Set.toAscListBack" [1] foldrFB (:) [] = toAscList #-} +{-# RULES "Set.toAscListBack" [1] forall q xs. foldrFB (:) q xs = toAscListThen xs q #-} {-# RULES "Set.toDescList" [~1] forall s . toDescList s = build (\c n -> foldlFB (\xs x -> c x xs) n s) #-} -{-# RULES "Set.toDescListBack" [1] foldlFB (\xs x -> x : xs) [] = toDescList #-} +{-# RULES "Set.toDescListBack" [1] forall q xs. foldlFB (\xs x -> x : xs) q xs = toDescListThen xs q #-} #endif -- | /O(n*log n)/. Create a set from a list of elements.