Skip to content

-O introduces space leak

consider the following variant of a popular space problem

initlast :: (()->[a]) -> ([a], a)
initlast xs = (init (xs ()), last (xs ()))

main = print $ case initlast (\()->[0..1000000000]) of
                 (init, last) -> (length init, last)

the long list has been wrapped in abstractions to avoid sharing, gaining constant space processing rather than the space leak in the original code - see

http://www.haskell.org/pipermail/haskell-cafe/2006-September/018447.html

http://www.haskell.org/pipermail/haskell-cafe/2006-September/018464.html

this works nicely if compiled without -O, but unfortunately, -O reintroduces the space leak (apparently lifting and sharing the common and space-expensive subexpression).

  1. I didn't see a ticket for this issue, so I wanted to record the example
  2. avoiding sharing isn't always possible, so it would be nice if one could

"bypass" sharing in such cases. in the old g-machine, that might have been as simple as introducing a pragma that tells the compiler to omit the update after the eval in the code for some subexpression (so the original application node would not be overwritten by the space-expensive result, trading time for space). is there a chance for a similar trick in GHC? so one might write code like this (handwaving:-):

initlast :: [a] -> ([a], a)
initlast xs = (init ({-# COPY #-} xs), last ({-# COPY #-} xs))

main = print $ case initlast [0..1000000000] of
                 (init, last) -> (length init, last)
Trac metadata
Trac field Value
Version 6.5
Type Bug
TypeOfFailure OtherFailure
Priority normal
Resolution Unresolved
Component Compiler
Test case
Differential revisions
BlockedBy
Related
Blocking
CC
Operating system Unknown
Architecture Unknown
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information