
#13080: Memory leak caused by nested monadic loops -------------------------------------+------------------------------------- Reporter: Feuerbach | Owner: Type: bug | Status: new Priority: normal | Milestone: 8.2.1 Component: Compiler | Version: 8.0.1 Resolution: | Keywords: Operating System: Unknown/Multiple | Architecture: Type of failure: Runtime | Unknown/Multiple performance bug | Test Case: Blocked By: | Blocking: Related Tickets: | Differential Rev(s): Wiki Page: | -------------------------------------+------------------------------------- Comment (by Feuerbach): David: If `foo` is marked as function-like by the programmer, `bar` and `baz` are recomputed on each invocation of `foo`. If `foo` is marked as value-like and is shared, `bar` and `baz` are shared, too. Furthermore, `bar` and `baz` could have their own annotations. Examples: {{{#!hs {-# FUNCTION_LIKE fib #-} fib = (fibs !!) where {- VALUE_LIKE fibs #-} fibs = 0 : 1 : zipWith (+) fibs (tail fibs) }}} {{{#!hs {-# VALUE_LIKE val #-} val = sum $ map f [1..10^6] where {-# FUNCTION_LIKE f #-} f = (+5) . (^2) }}} Now, what would FUNCTION_LIKE mean, exactly? In the `fib` example above, there can be two interpretations: 1. Don't bother "remembering" the PAP `(!!) fibs`, but do remember something like `fibs !! n`. 2. Don't even remember `fibs !! n`. The second interpretation is useful in cases like {{{#!hs mk_action :: Monad m => Int -> m () mk_action = flip replicateM_ (return ()) }}} where we may want to say, "don't bother to remember either the expansion or the result of mk_action". So, simple FUNCTION_LIKE can be ambiguous. What if we annotated functions with arities? Assigning an explicit arity to a function means that: 1. ghc attempts to perform eta reductions or expansions to match the declared arity; 2. ghc doesn't float things out of lambdas with declared arity >= 1. E.g. following Reid's example (https://ghc.haskell.org/trac/ghc/timeline?from=2017-01-07T14%3A42%3A24Z&precision=second), he could write {{{#!hs poll a = r >>= f where {-# ARITY 1 f #-} f _ -> poll a }}} and ghc would not transform `f` to `(let s = poll a in \_ -> s)`. And, of course, the original problem could be easily solved by annotating `poll` with the correct arity, as I point out in the blog post. It is also possible that these two things — forcing eta-expansion and not floating out local bindings — should be two different and orthogonal pragmass. What do you all think? -- Ticket URL: http://ghc.haskell.org/trac/ghc/ticket/13080#comment:17 GHC http://www.haskell.org/ghc/ The Glasgow Haskell Compiler