summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDavid Feuer <David.Feuer@gmail.com>2014-10-01 15:42:27 +0200
committerJoachim Breitner <mail@joachim-breitner.de>2014-10-01 15:46:14 +0200
commit6680f4fdebf23c1d8e443f2c658e3bc3ab43f295 (patch)
tree4e92d12a541bf1ab139e322b59c76076f8c63c00
parent7fdedf05b2d267dda6549e71d5a9da23110c3881 (diff)
downloadhaskell-6680f4fdebf23c1d8e443f2c658e3bc3ab43f295.tar.gz
Make mapAccumL a good consumerwip/validate-T9502
This fixes #9502.
-rw-r--r--libraries/base/Data/OldList.hs17
-rw-r--r--libraries/base/changelog.md2
2 files changed, 18 insertions, 1 deletions
diff --git a/libraries/base/Data/OldList.hs b/libraries/base/Data/OldList.hs
index fe0f38e284..9b6a431422 100644
--- a/libraries/base/Data/OldList.hs
+++ b/libraries/base/Data/OldList.hs
@@ -481,11 +481,28 @@ mapAccumL :: (acc -> x -> (acc, y)) -- Function of elt of input list
-> acc -- Initial accumulator
-> [x] -- Input list
-> (acc, [y]) -- Final accumulator and result list
+{-# NOINLINE [1] mapAccumL #-}
mapAccumL _ s [] = (s, [])
mapAccumL f s (x:xs) = (s'',y:ys)
where (s', y ) = f s x
(s'',ys) = mapAccumL f s' xs
+{-# RULES
+"mapAccumL" [~1] forall f s xs . mapAccumL f s xs = foldr (mapAccumLF f) pairWithNil xs s
+"mapAccumLList" [1] forall f s xs . foldr (mapAccumLF f) pairWithNil xs s = mapAccumL f s xs
+ #-}
+
+pairWithNil :: acc -> (acc, [y])
+{-# INLINE [0] pairWithNil #-}
+pairWithNil x = (x, [])
+
+mapAccumLF :: (acc -> x -> (acc, y)) -> x -> (acc -> (acc, [y])) -> acc -> (acc, [y])
+{-# INLINE [0] mapAccumLF #-}
+mapAccumLF f = \x r s -> let (s', y) = f s x
+ (s'', ys) = r s'
+ in (s'', y:ys)
+
+
-- | The 'mapAccumR' function behaves like a combination of 'map' and
-- 'foldr'; it applies a function to each element of a list, passing
-- an accumulating parameter from right to left, and returning a final
diff --git a/libraries/base/changelog.md b/libraries/base/changelog.md
index c594c2fcf4..09b749afd6 100644
--- a/libraries/base/changelog.md
+++ b/libraries/base/changelog.md
@@ -77,7 +77,7 @@
second argument, so that the fusion RULES for it do not change the
semantics. (#9596)
- * `scanr` now takes part in list fusion (#9355)
+ * `scanr` and `mapAccumL` now take part in list fusion (#9355, #9502)
## 4.7.0.1 *Jul 2014*