[commit: ghc] master: Make scanr a good producer and consumer (4e1dfc3)

git at git.haskell.org git at git.haskell.org
Wed Oct 1 16:21:33 UTC 2014


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/4e1dfc3767167dddd0e151a2df8305b12aa0f49c/ghc

>---------------------------------------------------------------

commit 4e1dfc3767167dddd0e151a2df8305b12aa0f49c
Author: David Feuer <David.Feuer at gmail.com>
Date:   Wed Oct 1 15:24:43 2014 +0200

    Make scanr a good producer and consumer
    
    This fixes #9355.


>---------------------------------------------------------------

4e1dfc3767167dddd0e151a2df8305b12aa0f49c
 libraries/base/GHC/List.lhs | 18 ++++++++++++++++++
 libraries/base/changelog.md |  2 ++
 2 files changed, 20 insertions(+)

diff --git a/libraries/base/GHC/List.lhs b/libraries/base/GHC/List.lhs
index 8c8e4bb..51f68ab 100644
--- a/libraries/base/GHC/List.lhs
+++ b/libraries/base/GHC/List.lhs
@@ -229,11 +229,29 @@ foldr1 _ []             =  errorEmptyList "foldr1"
 --
 -- > head (scanr f z xs) == foldr f z xs.
 
+{-# NOINLINE [1] scanr #-}
 scanr                   :: (a -> b -> b) -> b -> [a] -> [b]
 scanr _ q0 []           =  [q0]
 scanr f q0 (x:xs)       =  f x q : qs
                            where qs@(q:_) = scanr f q0 xs
 
+{-# INLINE [0] strictUncurryScanr #-}
+strictUncurryScanr :: (a -> b -> c) -> (a, b) -> c
+strictUncurryScanr f pair = case pair of
+                              (x, y) -> f x y
+
+{-# INLINE [0] scanrFB #-}
+scanrFB :: (a -> b -> b) -> (b -> c -> c) -> a -> (b, c) -> (b, c)
+scanrFB f c = \x (r, est) -> (f x r, r `c` est)
+
+{-# RULES
+"scanr" [~1] forall f q0 ls . scanr f q0 ls =
+  build (\c n -> strictUncurryScanr c (foldr (scanrFB f c) (q0,n) ls))
+"scanrList" [1] forall f q0 ls .
+               strictUncurryScanr (:) (foldr (scanrFB f (:)) (q0,[]) ls) =
+                 scanr f q0 ls
+ #-}
+
 -- | 'scanr1' is a variant of 'scanr' that has no starting value argument.
 
 scanr1                  :: (a -> a -> a) -> [a] -> [a]
diff --git a/libraries/base/changelog.md b/libraries/base/changelog.md
index 7529782..c594c2f 100644
--- a/libraries/base/changelog.md
+++ b/libraries/base/changelog.md
@@ -77,6 +77,8 @@
     second argument, so that the fusion RULES for it do not change the
     semantics. (#9596)
 
+  * `scanr` now takes part in list fusion (#9355)
+
 ## 4.7.0.1  *Jul 2014*
 
   * Bundled with GHC 7.8.3



More information about the ghc-commits mailing list