Thoughts on CallStack and withFrozenCallStack

Edward Z. Yang ezyang at
Wed Sep 7 22:10:27 UTC 2016

I've been adding CallStack to Cabal's source code, and I noticed
a common pattern that doesn't seem to be supported by the GHC.Stack

Imagine I'm writing a general purpose logging function:

    debug :: Verbosity -> String -> IO ()

I'd like this function to print out the SrcLoc of the person who
called; as an additional requirement, I only want to print the
top-most stack frame by default (someone can ask for the full
stack if they really want to).

If I look at callStack, it is going to contain a stack frame for debug
itself. That's not so great; the obvious way to fix this is to pop off
the irrelevant frame manually.  But now suppose that I have a pprDebug
which itself calls debug.  I don't want pprDebug to show up in the stack

Declaratively, I want to say, "Please don't add me to the call stack",
at the function *definition*, not the call-site (which is what
withFrozenCallStack) gives me.  Does this seem like a reasonable request?

I have several other ways to do this:

    - You could just use withFrozenCallStack at the definition site.
      Then when pprDebug calls debug, debug will get the call stack that
      pprDebug had; thus, there will always only be one irrelevant frame
      to pop off.

    - One problem with using withFrozenCallStack is that you *do* lose
      useful trace information, which you kind of might actually want
      if you are being verbose.  So it almost seems like, the frozen
      API should still *push* frames, but just not make them visible
      by default.

    - Something that does NOT work is having functions edit the call
      stack to remove themselves. There's no way to tell if the stack
      is frozen or not, and thus no way to tell if you are actually
      on the stack (and need to remove it.)


More information about the ghc-devs mailing list