genericLength is implemented, as of base 4.12, as:
genericLength :: (Num i) => [a] -> i
{-# NOINLINE [1] genericLength #-}
genericLength [] = 0
genericLength (_:l) = 1 + genericLength l
{-# RULES
"genericLengthInt" genericLength = (strictGenericLength :: [a] -> Int);
"genericLengthInteger" genericLength = (strictGenericLength :: [a] -> Integer);
#-}
strictGenericLength :: (Num i) => [b] -> i
strictGenericLength l = gl l 0
where
gl [] a = a
gl (_:xs) a = let a' = a + 1 in a' `seq` gl xs a'
which is basically a foldr, except that for Int and Integer it performs a foldl' instead.
Why does it not use foldl' in all cases? Doesn't foldr build up large thunks for long lists?
genericLength is implemented with things like Peano numbers in mind:
data Peano = Zero | Succ Peano
Numbers using this representation can be non-strict, so an operation like genericLength [1..] > 5 returns True instead of failing to terminate.
For most other reasonable implementations of Num, the foldr in genericLength does indeed cause the problems you mention.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With