# \[Well-Typed Blog\] Better Haskell stack traces via user annotations

**URL:** <https://discourse.haskell.org/t/well-typed-blog-better-haskell-stack-traces-via-user-annotations/12901>\
**Category:** Links\
**Created:** [September 4, 2025, 9:05am UTC](https://discourse.haskell.org/t/well-typed-blog-better-haskell-stack-traces-via-user-annotations/12901 "2025-09-04T09:05:17Z")\
**Posts on this page:** 5\
**Page:** 1

<div class="post-metadata">

**Author:** ![adamgundry](https://avatars.discourse-cdn.com/v4/letter/a/34f0e0/32.png) [@adamgundry](https://discourse.haskell.org/u/adamgundry)\
**Post date:** [September 4, 2025, 9:05am UTC](https://discourse.haskell.org/t/well-typed-blog-better-haskell-stack-traces-via-user-annotations/12901/1 "2025-09-04T09:05:17Z")

</div>

> **[Better Haskell stack traces via user annotations](https://www.well-typed.com/blog/2025/09/better-haskell-stack-traces/)**

---

<div class="post-metadata">

**Author:** ![jaror](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/jaror/32/3271_2.png) [@jaror](https://discourse.haskell.org/u/jaror)\
**Post date:** [September 4, 2025, 9:23am UTC](https://discourse.haskell.org/t/well-typed-blog-better-haskell-stack-traces-via-user-annotations/12901/2 "2025-09-04T09:23:00Z")

</div>

I think people often want to automatically annotate all their functions. I recently figured out that you can get pretty good cost centre stack traces by building with profiling and using `-fprof-callers="*.*"`. This adds the annotations after optimizations, so it does not have much overhead.

- [hmatrix - Not able to print out call stack in haskell - Stack Overflow](https://stackoverflow.com/a/79679731/15207568)
- [Jaro Reinders (he/him): "Did anyone know you can use `-fprof-callers="\*.\*"…" - SURF Mastodon](https://social.edu.nl/@jaror/114785130034001917)
- [Jaro Reinders (he/him): "When compiling #Haskell programs, `-fprof-auto-ca…" - SURF Mastodon](https://social.edu.nl/@jaror/114785205408380422)

---

<div class="post-metadata">

**Author:** ![adamgundry](https://avatars.discourse-cdn.com/v4/letter/a/34f0e0/32.png) [@adamgundry](https://discourse.haskell.org/u/adamgundry)\
**Post date:** [September 4, 2025, 9:40am UTC](https://discourse.haskell.org/t/well-typed-blog-better-haskell-stack-traces-via-user-annotations/12901/3 "2025-09-04T09:40:53Z")

</div>

Yes, if you can afford the use of profiling mode then judiciously inserting cost centres after optimization is often the way to go. (I’ve not tried ``-fprof-callers="*.*"`, do you know how it compares to `-fprof-late`?). That’s often good enough in development.

But merely turning on profiling mode causes enough of a performance hit to make it infeasible in some production cases (because of the extra word in heap objects), at which point it is crucial to use methods that don’t require the profiling runtime (e.g. IPE info + annotations).

---

<div class="post-metadata">

**Author:** ![TeofilC](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/teofilc/32/3987_2.png) [@TeofilC](https://discourse.haskell.org/u/TeofilC)\
**Post date:** [September 4, 2025, 9:53am UTC](https://discourse.haskell.org/t/well-typed-blog-better-haskell-stack-traces-via-user-annotations/12901/4 "2025-09-04T09:53:29Z")

</div>

Maybe it would be possible to add these annotations to all functions using a GHC plugin (or a GHC flag that does the equivalent of the profiling one)?

---

<div class="post-metadata">

**Author:** ![jaror](https://sea2.discourse-cdn.com/flex002/user_avatar/discourse.haskell.org/jaror/32/3271_2.png) [@jaror](https://discourse.haskell.org/u/jaror)\
**Post date:** [September 4, 2025, 9:59am UTC](https://discourse.haskell.org/t/well-typed-blog-better-haskell-stack-traces-via-user-annotations/12901/5 "2025-09-04T09:59:46Z")

</div>

> [@adamgundry](#):
>
> I’ve not tried `-fprof-callers="*.*"`, do you know how it compares to `-fprof-late`?

I thought the main difference was that it reports the call site and not the definition site. Consider this program:

```haskell
import Control.Exception.Backtrace

import Prelude hiding (div)
import qualified Prelude

div :: Int -> Int -> Int
div x 0 = error "Division by zero"
div x y = Prelude.div x y
{-# NOINLINE div #-}

foo :: Int -> Int
foo x = y1 + y2 + y3 where
  y1 = div x 2
  y2 = div 3 x
  y3 = div x 4
{-# NOINLINE foo #-}

main = do
  setBacktraceMechanismState CostCentreBacktrace True
  print (foo 0)

```

I want the call stack to point out line that the problematic `div` is called on line 14, not just that one of the `div` calls in `foo` is problematic.

The `-fprof-auto-calls` option does do that (I’ve truncated GHC.Internal entries):

```haskell
Cost-centre stack backtrace:
  Main.CAF (<entire-module>)
  Main.main (T.hs:(18,8)-(20,15))
  Main.main (T.hs:20:3-15)
  Main.main (T.hs:20:10-14)
  Main.foo.y2 (T.hs:14:8-14)
  Main.div (T.hs:7:11-34)

```

I thought `-fprof-callers="*.*"` would do the same, but it seems I am mistaken:

```haskell
Cost-centre stack backtrace:
  Main.CAF (<entire-module>)
  Main.Main.main(calling:Main.foo) (T.hs:18:1-4)
  Main.Main.foo(calling:Main.div) (T.hs:12:1-3)

```

For comparison, here’s what `-fprof-late` reports:

```haskell
Cost-centre stack backtrace:
  Main.CAF (<entire-module>)
  Main.main (T.hs:18:1-4)
  Main.foo (T.hs:12:1-3)
  Main.div (T.hs:7:1-3)

```
