# `require-callstack`
Haskell has opt-in call stacks through the use of the `HasCallStack` constraint.
One unfortunate aspect of this design is that the resulting `CallStack` can be truncated if any function in the call list omits the constraint.
```haskell
foo :: HasCallStack => Int -> String
foo = error "oh no"
bar :: HasCallStack => Int -> String
bar = foo . negate
baz :: Int -> String
baz = bar . (* 2)
main :: IO ()
main = do
print $ baz 5
```
Running this code will fail with an `ErrorCall "oh no"` exception.
The attached `CallStack` will only mention `foo` and `bar` - `baz` *will not* be present, nor will `main`.
A truncated `CallStack` isn't nearly as useful as you might like.
One solution is the [`annotated-exception`](https://www.stackage.org/lts-21.1/package/annotated-exception-0.2.0.4) library, which can attach `CallStack` to any thrown exception, and `catch` is guaranteed to add a stack frame at the catch-site for any exception that passes through.
However, it's *still* nice to have `HasCallStack` entries on functions - then you get the name of the function, which makes diagnosing an error report easier.
This library introduces a type `RequireCallStack`.
Unlike `HasCallStack`, this isn't automagically solved - if you call a function that has `RequireCallStack` in the constraint, you must either call `provideCallStack` to discharge the constraint, or add `RequireCallStack` to the signature of the function you're defining.
```haskell
panic :: RequireCallStack => String -> a
panic = error
foo :: RequireCallStack => Int -> String
foo = panic "oh no"
bar :: RequireCallStack => Int -> String
bar = foo . negate
baz :: Int -> String
baz = bar . (* 2)
main :: IO ()
main = do
print $ baz 5
```
This code will fail with a compile-time error:
> ```
> /home/matt/Projects/require-callstack/test/Main.hs:30:5: error: [GHC-39999]
> • No instance for ‘RequireCallStack.Internal.Add_RequireCallStack_ToFunctionContext_OrUse_provideCallStack’
> arising from a use of ‘bar’
> ....
> |
> 30 | bar . (* 2)
> | ^^^
> ```
The error message, read carefully, will tell you how to solve the issue.
If we then write:
```haskell
panic :: RequireCallStack => String -> a
panic = error
foo :: RequireCallStack => Int -> String
foo = panic "oh no"
bar :: RequireCallStack => Int -> String
bar = foo . negate
baz :: RequireCallStack => Int -> String
baz = bar . (* 2)
main :: IO ()
main = provideCallStack $ do
print $ baz 5
```
Then the code compiles and works as expected.