-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).
- I didn't see a ticket for this issue, so I wanted to record the example
- 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 |