From f5890dc1b5296b44d036df768641e2be29075d12 Mon Sep 17 00:00:00 2001
From: "simonpj@microsoft"
Date: Mon, 8 May 2006 14:27:26 +0000
Subject: [PATCH] Make length a good consumer
Make length into a good consumer. Fixes Trac bug #707.
(Before length simply didn't use foldr.)
---
GHC/List.lhs | 21 +++++++++++++++------
1 file changed, 15 insertions(+), 6 deletions(-)
diff --git a/GHC/List.lhs b/GHC/List.lhs
index 60fc90b..689637e 100644
--- a/GHC/List.lhs
+++ b/GHC/List.lhs
@@ -111,12 +111,21 @@ null (_:_) = False
-- | 'length' returns the length of a finite list as an 'Int'.
-- It is an instance of the more general 'Data.List.genericLength',
-- the result type of which may be any kind of number.
-length :: [a] -> Int
-length l = len l 0#
- where
- len :: [a] -> Int# -> Int
- len [] a# = I# a#
- len (_:xs) a# = len xs (a# +# 1#)
+length :: [a] -> Int
+length l = lenAcc 0# l
+
+{-# RULES
+"length" [~1] forall xs. length xs = foldr incL (I# 0#) xs
+"lenAcc" [1] forall n#. foldr incL (I# n#) = lenAcc n#
+ #-}
+
+incL :: a -> Int -> Int -- Internal
+{-# NOINLINE [0] incL #-}
+incL x n = n `plusInt` oneInt
+
+lenAcc :: Int# -> [a] -> Int -- Internal
+lenAcc a# [] = I# a#
+lenAcc a# (_:xs) = lenAcc (a# +# 1#) xs
-- | 'filter', applied to a predicate and a list, returns the list of
-- those elements that satisfy the predicate; i.e.,
--
1.9.1