Ticket #3999: intmap-folding.patch

File intmap-folding.patch, 6.6 KB (added by LouisWasserman, 3 years ago)

Adds foldrWithKey and foldlWithKey to Data.IntMap??, improves the Foldable instance, and adds useful deforesting rewrite rules.

Line 
1Wed Apr 21 17:59:32 CDT 2010  wasserman.louis@gmail.com
2  * foldrWithKey, foldlWithKey, an improved Foldable instance, and folding rewrite rules for Data.IntMap
3
4New patches:
5
6[foldrWithKey, foldlWithKey, an improved Foldable instance, and folding rewrite rules for Data.IntMap
7wasserman.louis@gmail.com**20100421225932
8 Ignore-this: d1d53c1d56e4e118076cc19a01d53524
9] {
10hunk ./Data/IntMap.hs 104
11             -- ** Fold
12             , fold
13             , foldWithKey
14+            , foldrWithKey
15+            , foldlWithKey
16 
17             -- * Conversion
18             , elems
19hunk ./Data/IntMap.hs 170
20 import Prelude hiding (lookup,map,filter,foldr,foldl,null)
21 import Data.Bits
22 import qualified Data.IntSet as IntSet
23+import qualified Data.List as List
24 import Data.Monoid (Monoid(..))
25 import Data.Maybe (fromMaybe)
26 import Data.Typeable
27hunk ./Data/IntMap.hs 174
28-import Data.Foldable (Foldable(foldMap))
29+import Data.Foldable (Foldable(foldMap,foldr,foldl))
30 import Data.Traversable (Traversable(traverse))
31 import Control.Applicative (Applicative(pure,(<*>)),(<$>))
32 import Control.Monad ( liftM )
33hunk ./Data/IntMap.hs 260
34     foldMap _ Nil = mempty
35     foldMap f (Tip _k v) = f v
36     foldMap f (Bin _ _ l r) = foldMap f l `mappend` foldMap f r
37+    foldr f = foldrWithKey (const f)
38+    foldl f = foldlWithKey (const . f)
39 
40 instance Traversable IntMap where
41     traverse _ Nil = pure Nil
42hunk ./Data/IntMap.hs 1367
43 
44 foldWithKey :: (Key -> a -> b -> b) -> b -> IntMap a -> b
45 foldWithKey f z t
46-  = foldr f z t
47+  = foldrWithKey f z t
48 
49hunk ./Data/IntMap.hs 1369
50-foldr :: (Key -> a -> b -> b) -> b -> IntMap a -> b
51-foldr f z t
52+-- | /O(n)/. Fold the keys and values in the map, such that
53+-- @'foldrWithKey' f z == 'Prelude.foldr' ('uncurry' f) z . 'toAscList'@.
54+-- For example,
55+--
56+-- > keys map = foldrWithKey (\k x ks -> k:ks) [] map
57+--
58+-- > let f k a result = result ++ "(" ++ (show k) ++ ":" ++ a ++ ")"
59+-- > foldrWithKey f "Map: " (fromList [(5,"a"), (3,"b")]) == "Map: (5:a)(3:b)"
60+foldrWithKey :: (Key -> a -> b -> b) -> b -> IntMap a -> b
61+foldrWithKey f z t
62   = case t of
63       Bin 0 m l r | m < 0 -> foldr' f (foldr' f z l) r  -- put negative numbers before.
64       Bin _ _ _ _ -> foldr' f z t
65hunk ./Data/IntMap.hs 1385
66       Tip k x     -> f k x z
67       Nil         -> z
68 
69+-- | /O(n)/.  Fold the keys and values in the map, such that
70+-- @'foldlWithKey' f z == 'Prelude.foldl' ('uncurry' . f) z . 'toAscList'@.
71+foldlWithKey :: (b -> Key -> a -> b) -> b -> IntMap a -> b
72+foldlWithKey f z t
73+  = case t of
74+      Bin 0 m l r | m < 0 -> foldl' f (foldl' f z r) l
75+      Bin _ _ _ _ -> foldl' f z t
76+      Tip k x     -> f z k x
77+      Nil         -> z
78+
79 foldr' :: (Key -> a -> b -> b) -> b -> IntMap a -> b
80 foldr' f z t
81   = case t of
82hunk ./Data/IntMap.hs 1402
83       Tip k x     -> f k x z
84       Nil         -> z
85 
86-
87+foldl' :: (b -> Key -> a -> b) -> b -> IntMap a -> b
88+foldl' f z t
89+  = case t of
90+      Bin _ _ l r -> foldl' f (foldl' f z l) r
91+      Tip k x     -> f z k x
92+      Nil         -> z
93 
94 {--------------------------------------------------------------------
95   List variations
96hunk ./Data/IntMap.hs 1460
97 
98 toList :: IntMap a -> [(Key,a)]
99 toList t
100-  = foldWithKey (\k x xs -> (k,x):xs) [] t
101+  = toAscList t
102 
103hunk ./Data/IntMap.hs 1462
104+{-# NOINLINE [0] toAscList #-}
105 -- | /O(n)/. Convert the map to a list of key\/value pairs where the
106 -- keys are in ascending order.
107 --
108hunk ./Data/IntMap.hs 1470
109 
110 toAscList :: IntMap a -> [(Key,a)]
111 toAscList t   
112-  = -- NOTE: the following algorithm only works for big-endian trees
113-    let (pos,neg) = span (\(k,_) -> k >=0) (foldr (\k x xs -> (k,x):xs) [] t) in neg ++ pos
114+       = foldWithKey (\k x xs -> (k,x):xs) [] t
115+--   = -- NOTE: the following algorithm only works for big-endian trees
116+--     let (pos,neg) = span (\(k,_) -> k >=0) (foldrWithKey (\k x xs -> (k,x):xs) [] t) in neg ++ pos
117+--     QuickCheck indicates that these are equivalent, and really, if foldrWithKey doesn't fold negative
118+--     to positive, then that's a problem with foldrWithKey, not with toAscList...
119 
120 -- | /O(n*min(n,W))/. Create a map from a list of key\/value pairs.
121 --
122hunk ./Data/IntMap.hs 1951
123 
124 -}
125 
126+{-# RULES
127+       "foldr/Data.IntMap.elems" forall f z m . List.foldr f z (elems m) = foldr f z m;
128+       "foldl/Data.IntMap.elems" forall f z m . List.foldl f z (elems m) = foldl f z m;
129+       "foldr/Data.IntMap.keys" forall f z m . List.foldr f z (keys m) = foldrWithKey (\ k _ -> f k) z m;
130+       "foldl/Data.IntMap.keys" forall f z m . List.foldl f z (keys m) = foldlWithKey (\ z k _ -> f z k) z m;
131+       "foldr/Data.IntMap.toAscList" forall f z m . List.foldr f z (toAscList m) = foldrWithKey (curry f) z m;
132+       "foldl/Data.IntMap.toAscList" forall f z m . List.foldl f z (toAscList m) = foldlWithKey (curry . f) z m;
133+       #-}
134}
135
136Context:
137
138[Tweak layout to work with the alternative layout rule
139Ian Lynagh <igloo@earth.li>**20091129154519]
140[Disable building Data.Sequence (and dependents) for nhc98.
141Malcolm.Wallace@cs.york.ac.uk**20091124025653
142 There is some subtlety of polymorphically recursive datatypes and
143 type-class defaulting that nhc98's type system barfs over.
144]
145[Fix another instance of non-ghc breakage.
146Malcolm.Wallace@cs.york.ac.uk**20091123092637]
147[Add #ifdef around ghc-only (<$) as member of Functor class.
148Malcolm.Wallace@cs.york.ac.uk**20091123085155]
149[Fix broken code in non-GHC branch of an ifdef.
150Malcolm.Wallace@cs.york.ac.uk**20091123084824]
151[doc bugfix: correct description of index argument
152Ross Paterson <ross@soi.city.ac.uk>**20091028105532
153 Ignore-this: 9790e7bf422c4cb528722c03cfa4fed9
154 
155 As noted by iaefai on the libraries list.
156 
157 Please merge to STABLE.
158]
159[Bump version to 0.3.0.0
160Ian Lynagh <igloo@earth.li>**20090920141847]
161[update base dependency
162Ross Paterson <ross@soi.city.ac.uk>**20090916073125
163 Ignore-this: ad382ffc6c6a18c15364e6c072f19edb
164 
165 The package uses mkNoRepType and Data.Functor, which were not in the
166 stable branch of base-4.
167]
168[add fast version of <$ for Seq
169Ross Paterson <ross@soi.city.ac.uk>**20090916072812
170 Ignore-this: 5a39a7d31d39760ed589790b1118d240
171]
172[new methods for Data.Sequence (proposal #3271)
173Ross Paterson <ross@soi.city.ac.uk>**20090915173324
174 Ignore-this: cf17bedd709a6ab3448fd718dcdf62e7
175 
176 Adds a lot of new methods to Data.Sequence, mostly paralleling those
177 in Data.List.  Several of these are significantly faster than versions
178 implemented with the previous public interface.  In particular, replicate
179 takes O(log n) time and space instead of O(n).
180 (by Louis Wasserman)
181]
182[Fix "Cabal check" warnings
183Ian Lynagh <igloo@earth.li>**20090811215900]
184[TAG 2009-06-25
185Ian Lynagh <igloo@earth.li>**20090625160202]
186Patch bundle hash:
1872ea0d9855a86353654bdf26435a803d38b64164c