
On Mon, 12 Jan 2009 19:43:00 +0100
"Bas van Dijk"
On Mon, Jan 12, 2009 at 6:47 PM, Max Bolingbroke
wrote: GHC should indeed be doing so. I'm working (on and off) to work out some suitable heuristics and put the transformation into ghc -O2. There are a few wrinkles that still need sorting out, but preliminary indications are that it decreases the runtime of our standard benchmark suite, nofib, by 12% or so.
Great!
In the Stream library I'm developing at http://code.haskell.org/Stream I 'closurize' (for lack of a better name) all my functions. Here are a few random examples:
repeat :: a -> Stream a repeat x = repeat_x where repeat_x = x ::: repeat_x
cycle :: [a] -> Stream a cycle xs = cycle_xs where cycle_xs = foldr (:::) cycle_xs xs
deleteBy :: (a -> a -> Bool) -> a -> Stream a -> Stream a deleteBy eq x = deleteBy_eq_x where deleteBy_eq_x (y ::: ys) | eq x y = ys | otherwise = y ::: deleteBy_eq_x ys
Closurizing the functions in Data.Stream lead to 10% to 250% speedups!
Awesome! I tend to use Control.Monad.Fix.fix (which actually has nothing to do with monads, despite the package name) sometimes, for "closurizing" a recursive function. I am curious as to whether the "fix" style of recursive programming is likely to result in the same speedups. The fix-style equivalent to your repeat above, would be something like this: repeat x = fix $ \me -> x ::: me (I use "me" for the name of the recursive call, partly because it reminds me that it's a self-call, and partly because I find it amusing) -- Robin