Implement list fusion for {Int,}{MapSet}
authorJoachim Breitner <mail@joachim-breitner.de>
Wed, 21 Sep 2011 18:17:17 +0000 (20:17 +0200)
committerMilan Straka <fox@ucw.cz>
Fri, 25 Nov 2011 08:27:42 +0000 (09:27 +0100)
I am not fully convinced that it works well with the INLINEABLE pragmas,
but it won’t do harm this way either.

Data/IntMap/Base.hs
Data/IntSet.hs
Data/Map/Base.hs
Data/Set.hs

index 065beb9..0927f35 100644 (file)
@@ -192,7 +192,7 @@ import Data.Data (Data(..), mkNoRepType)
 #endif
 
 #if __GLASGOW_HASKELL__
-import GHC.Exts ( Word(..), Int(..), shiftRL# )
+import GHC.Exts ( Word(..), Int(..), shiftRL#, build )
 #else
 import Data.Word
 #endif
@@ -1481,6 +1481,7 @@ keysSet m = IntSet.fromDistinctAscList (keys m)
 
 
 -- | /O(n)/. Return all key\/value pairs in the map in ascending key order.
+-- Subject to list Fusion.
 --
 -- > assocs (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]
 -- > assocs empty == []
@@ -1493,7 +1494,8 @@ assocs m
 {--------------------------------------------------------------------
   Lists
 --------------------------------------------------------------------}
--- | /O(n)/. Convert the map to a list of key\/value pairs.
+-- | /O(n)/. Convert the map to a list of key\/value pairs. Subject to list
+-- fusion.
 --
 -- > toList (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]
 -- > toList empty == []
@@ -1502,6 +1504,13 @@ toList :: IntMap a -> [(Key,a)]
 toList
   = foldrWithKey (\k x xs -> (k,x):xs) []
 
+#if __GLASGOW_HASKELL__ >= 503
+-- List fusion for the above two functions
+{-# RULES "IntMap/toList" forall im . toList im = build (\c n -> foldrWithKey (\k x xs -> c (k,x) xs) n im) #-}
+{-# RULES "IntMap/assocs" forall im . assocs im = build (\c n -> foldrWithKey (\k x xs -> c (k,x) xs) n im) #-}
+#endif
+
+
 -- | /O(n)/. Convert the map to a list of key\/value pairs where the
 -- keys are in ascending order.
 --
index 58b12d4..b4f388f 100644 (file)
@@ -151,7 +151,7 @@ import Data.Data (Data(..), mkNoRepType)
 #endif
 
 #if __GLASGOW_HASKELL__
-import GHC.Exts ( Word(..), Int(..) )
+import GHC.Exts ( Word(..), Int(..), build )
 import GHC.Prim ( uncheckedShiftL#, uncheckedShiftRL#, indexInt8OffAddr# )
 #else
 import Data.Word
@@ -758,6 +758,7 @@ foldl' f z t =
   List variations
 --------------------------------------------------------------------}
 -- | /O(n)/. The elements of a set. (For sets, this is equivalent to toList.)
+-- Subject to list fusion
 elems :: IntSet -> [Int]
 elems t
   = toAscList t
@@ -765,15 +766,24 @@ elems t
 {--------------------------------------------------------------------
   Lists
 --------------------------------------------------------------------}
--- | /O(n)/. Convert the set to a list of elements.
+-- | /O(n)/. Convert the set to a list of elements. Subject to list fusion.
 toList :: IntSet -> [Int]
 toList t
   = toAscList t
 
--- | /O(n)/. Convert the set to an ascending list of elements.
+-- | /O(n)/. Convert the set to an ascending list of elements. Subject to list
+-- fusion.
 toAscList :: IntSet -> [Int]
 toAscList t = foldr (:) [] t
 
+#if __GLASGOW_HASKELL__ >= 503
+-- List fusion for the above three functions
+{-# RULES "IntSet/toList" forall is . toList is = build (\c n -> foldr c n is) #-}
+{-# RULES "IntSet/toAscList" forall is . toAscList is = build (\c n -> foldr c n is) #-}
+{-# RULES "IntSet/elems" forall is . elems is = build (\c n -> foldr c n is) #-}
+#endif
+
+
 -- | /O(n*min(n,W))/. Create a set from a list of integers.
 fromList :: [Int] -> IntSet
 fromList xs
index 1e6096f..df6acc5 100644 (file)
@@ -228,6 +228,9 @@ import Data.Typeable
 import Control.DeepSeq (NFData(rnf))
 
 #if __GLASGOW_HASKELL__
+#if __GLASGOW_HASKELL__ >= 503
+import GHC.Exts ( build )
+#endif
 import Text.Read
 import Data.Data
 #endif
@@ -1817,7 +1820,7 @@ fromListWithKey f xs
 {-# INLINABLE fromListWithKey #-}
 #endif
 
--- | /O(n)/. Convert to a list of key\/value pairs.
+-- | /O(n)/. Convert to a list of key\/value pairs. Subject to list fusion.
 --
 -- > toList (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]
 -- > toList empty == []
@@ -1828,7 +1831,7 @@ toList t      = toAscList t
 {-# INLINABLE toList #-}
 #endif
 
--- | /O(n)/. Convert to an ascending list.
+-- | /O(n)/. Convert to an ascending list. Subject to list fusion.
 --
 -- > toAscList (fromList [(5,"a"), (3,"b")]) == [(3,"b"), (5,"a")]
 
@@ -1838,13 +1841,21 @@ toAscList t   = foldrWithKey (\k x xs -> (k,x):xs) [] t
 {-# INLINABLE toAscList #-}
 #endif
 
--- | /O(n)/. Convert to a descending list.
+-- | /O(n)/. Convert to a descending list. Subject to list fusion.
 toDescList :: Map k a -> [(k,a)]
 toDescList t  = foldlWithKey (\xs k x -> (k,x):xs) [] t
 #if __GLASGOW_HASKELL__ >= 700
 {-# INLINABLE toDescList #-}
 #endif
 
+#if __GLASGOW_HASKELL__ >= 503
+-- List fusion for the above four functions
+{-# RULES "Map/assocs" forall m . assocs m = build (\c n -> foldrWithKey (\k x xs -> c (k,x) xs) n m) #-}
+{-# RULES "Map/toList" forall m . toList m = build (\c n -> foldrWithKey (\k x xs -> c (k,x) xs) n m) #-}
+{-# RULES "Map/toAscList" forall m . toAscList m = build (\c n -> foldrWithKey (\k x xs -> c (k,x) xs) n m) #-}
+{-# RULES "Map/toDescList" forall m . toDescList m = build (\c n -> foldlWithKey (\xs k x -> c (k,x) xs) n m) #-}
+#endif
+
 {--------------------------------------------------------------------
   Building trees from ascending/descending lists can be done in linear time.
 
index daab0c6..1ae2ca6 100644 (file)
@@ -158,6 +158,9 @@ import qualified List
 #if __GLASGOW_HASKELL__
 import Text.Read
 import Data.Data
+#if __GLASGOW_HASKELL__ >= 503
+import GHC.Exts ( build )
+#endif
 #endif
 
 -- Use macros to define strictness of functions.
@@ -618,7 +621,7 @@ foldl' f = go
 {--------------------------------------------------------------------
   List variations
 --------------------------------------------------------------------}
--- | /O(n)/. The elements of a set.
+-- | /O(n)/. The elements of a set. Subject to list fusion.
 elems :: Set a -> [a]
 elems = toList
 #if __GLASGOW_HASKELL__ >= 700
@@ -628,20 +631,27 @@ elems = toList
 {--------------------------------------------------------------------
   Lists
 --------------------------------------------------------------------}
--- | /O(n)/. Convert the set to a list of elements.
+-- | /O(n)/. Convert the set to a list of elements. Subject to list fusion.
 toList :: Set a -> [a]
 toList = toAscList
 #if __GLASGOW_HASKELL__ >= 700
 {-# INLINABLE toList #-}
 #endif
 
--- | /O(n)/. Convert the set to an ascending list of elements.
+-- | /O(n)/. Convert the set to an ascending list of elements. Subject to list fusion.
 toAscList :: Set a -> [a]
 toAscList = foldr (:) []
 #if __GLASGOW_HASKELL__ >= 700
 {-# INLINABLE toAscList #-}
 #endif
 
+#if __GLASGOW_HASKELL__ >= 503
+-- List fusion for the above three functions
+{-# RULES "Set/toList" forall s . toList s = build (\c n -> foldr c n s) #-}
+{-# RULES "Set/toAscList" forall s . toAscList s = build (\c n -> foldr c n s) #-}
+{-# RULES "Set/elems" forall s . elems s = build (\c n -> foldr c n s) #-}
+#endif
+
 -- | /O(n*log n)/. Create a set from a list of elements.
 fromList :: Ord a => [a] -> Set a
 fromList = foldlStrict ins empty