[Haskell-cafe] Re: Profiling makes memory leak go away? Is Haskell a practical language?

apfelmus apfelmus at quantentunnel.de
Tue Apr 10 06:14:47 EDT 2007

Oren Ben-Kiki wrote:
> The code is in http://hpaste.org/1314#a1 if anyone at all is willing
> to take pity on me and explain what I'm doing wrong.

There is an important point to note about streaming, namely that it
conflicts with knowing whether the input is syntactically correct or
not. In other words, evaluating (rResult reply) parses the hole input to
the bitter end. For example, take your input data

  cycle "a\n" = "a\na\na\na\n..."

Can we determine whether (rResult reply) is Nothing or Just after
reading the first 'a'? No, we can't because the hole parse could fail
far to the end resulting in Nothing.

You've probably noticed this already and introduced rToken for that
reason but I'm not sure.

> Chasing down my memory leak I got into a weird situation where adding
> a magic manual SCC section and compiling with -prof makes the leak
> disappear.

That sounds fishy. Note that manual SCC annotations + optimization
currently is a bit buggy in GHC, in the sense that optimization disturbs
correct cost attribution.

Does the program eat the output of yes 'a' without memory explosion
showed by "top"? If so, it could perhaps be a problem of the
optimization phase which maybe expands

  D.append parsed (case result of ...)


  case result of {
      Nothing -> D.append parsed D.empty
      Just .. -> D.append parsed (D.singleton...) }

The latter won't stream because of the reason noted above. But it's
highly unlikely that GHC performs a transformation that changes
semantics this radically.

> I can achieve the results I want in very short elegant code...

In my opinion, your streaming parser is not as elegant as it could be
which makes it hard to read the code. With monad transformers, we almost

  Parser a ~= StateT State (WriterT (D.DList Token) Maybe) a
           ~= State -> (D.DList Token, Maybe (a,State))

Your Parser is slightly different but I think that the monad instances
behave exactly the same way. The power functional programming is to
assemble big things from small things. Monad transformers supply tons of
small monads that you can reuse to build big monads. In a sense, the
many pattern matches on Maybe have already been written down in general
form by someone else.

Also, I'm really missing type signatures, especially for many. When
reading the code, I expected

  many :: Parser a -> Parser [a]

but had to conclude

  many :: Parser a -> Parser ()

by inspecting its code.


More information about the Haskell-Cafe mailing list