CallStacks are a lightweight method of obtaining a partial
call-stack at any point in the program.
A function can request its call-site with the
HasCallStack
constraint. For example, we can define
putStrLnWithCallStack :: HasCallStack => String -> IO ()
as a variant of
putStrLn that will get its call-site and
print it, along with the string given as argument. We can access the
call-stack inside
putStrLnWithCallStack with
callStack.
>>> :{
putStrLnWithCallStack :: HasCallStack => String -> IO ()
putStrLnWithCallStack msg = do
putStrLn msg
putStrLn (prettyCallStack callStack)
:}
Thus, if we call
putStrLnWithCallStack we will get a
formatted call-stack alongside our string.
>>> putStrLnWithCallStack "hello"
hello
CallStack (from HasCallStack):
putStrLnWithCallStack, called at <interactive>:... in interactive:Ghci...
GHC solves
HasCallStack constraints in three steps:
- If there is a CallStack in scope -- i.e. the enclosing
function has a HasCallStack constraint -- GHC will append the
new call-site to the existing CallStack.
- If there is no CallStack in scope -- e.g. in the GHCi
session above -- and the enclosing definition does not have an
explicit type signature, GHC will infer a HasCallStack
constraint for the enclosing definition (subject to the monomorphism
restriction).
- If there is no CallStack in scope and the enclosing
definition has an explicit type signature, GHC will solve the
HasCallStack constraint for the singleton CallStack
containing just the current call-site.
CallStacks do not interact with the RTS and do not require
compilation with
-prof. On the other hand, as they are built
up explicitly via the
HasCallStack constraints, they will
generally not contain as much information as the simulated call-stacks
maintained by the RTS.
A
CallStack is a
[(String, SrcLoc)]. The
String is the name of function that was called, the
SrcLoc is the call-site. The list is ordered with the most
recently called function at the head.
NOTE: The intrepid user may notice that
HasCallStack is just an
alias for an implicit parameter
?callStack :: CallStack. This
is an implementation detail and
should not be considered part
of the
CallStack API, we may decide to change the
implementation in the future.
@since base-4.8.1.0