
Hi, I'm using GHC 7.0.1. I found that recursive overloaded functions tend to leak memory when compiled with full-laziness optimization on. Here is a simple case. -- TestSub.hs {-# LANGUAGE BangPatterns #-} module TestSub where {-# NOINLINE factorial #-} factorial :: (Num a) => a -> a -> a factorial !n !acc = if n == 0 then acc else factorial (n - 1) (acc * n) -- main.hs import TestSub factorial1 :: Int -> Int -> Int factorial1 = factorial main = do n <- readLn print $ factorial1 n 1 main This program should run in constant space, and compiled with -O0 or -O2 -fno-full-laziness, it does. However with -O2, it takes a linear amount of memory. The core for factorial looks like this: TestSub.factorial = \ (@ a_ajm) ($dNum_slz :: GHC.Num.Num a_ajm) -> let { a_slA :: GHC.Classes.Eq a_ajm [LclId] a_slA = GHC.Num.$p1Num @ a_ajm $dNum_slz } in let { lvl2_slC :: a_ajm -> a_ajm -> a_ajm [LclId] lvl2_slC = TestSub.factorial @ a_ajm $dNum_slz } in ... The problem is that lvl2_slC closure is created whenever factorial is applied to a Num dictionary, and kept alive until that application is GCed. In this program it never happens, because an application to the Num Int dictionary is referred to by the factorial1 CAF, and it recursively keeps the whole chain of closures alive. I know that full laziness transformation *sometimes* causes a space leak, but this looks like a bad result to me, because: - It looks like there is no point building a lot of equivalent closures, instead of one. - A lot of code can suffer from this behavior, because overloaded recursive functions are fairly common. For example, unfoldConvStream function from the latest iteratee package suffers from this problem, if I understand correctly. Does anyone have an idea on whether this can be fixed in GHC, or how to work around this problem? Regards, Takano Akio