Skip to content

Commit

Permalink
Implement list fusion for {Int,}{MapSet}
Browse files Browse the repository at this point in the history
I am not fully convinced that it works well with the INLINEABLE pragmas,
but it won’t do harm this way either.
  • Loading branch information
nomeata authored and foxik committed Nov 25, 2011
1 parent 5c4a8b9 commit 8b53db1
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 11 deletions.
13 changes: 11 additions & 2 deletions Data/IntMap/Base.hs
Expand Up @@ -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
Expand Down Expand Up @@ -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 == []
Expand All @@ -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 == []
Expand All @@ -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.
--
Expand Down
16 changes: 13 additions & 3 deletions Data/IntSet.hs
Expand Up @@ -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
Expand Down Expand Up @@ -758,22 +758,32 @@ 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

{--------------------------------------------------------------------
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
Expand Down
17 changes: 14 additions & 3 deletions Data/Map/Base.hs
Expand Up @@ -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
Expand Down Expand Up @@ -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 == []
Expand All @@ -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")]

Expand All @@ -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.
Expand Down
16 changes: 13 additions & 3 deletions Data/Set.hs
Expand Up @@ -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.
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand Down

0 comments on commit 8b53db1

Please sign in to comment.