If you can run the code in ghci, then the debugger can do everything you want. Here's a program that raises an exception
foo s i
| i == 57 = read s
| otherwise = i
main = mapM_ (print . foo "") [1..100]
Now load it into ghci and use the debugger, as documented here:
http://www.haskell.org/ghc/docs/latest/html/users_guide/ghci-debugger.html#ghci-debugger-exceptions
> ghci test.hs
*Main> :set -fbreak-on-error
*Main> :trace main
1
2
... snipped 3 through 55 ...
56
Stopped at <exception thrown>
_exception :: e = _
[<exception thrown>] *Main> :back
Logged breakpoint at test.hs:2:15-20
_result :: a
s :: String
[-1: test.hs:2:15-20] *Main> :list
1 foo s i
2 | i == 57 = **read s**
3 | otherwise = i
[-1: test.hs:2:15-20] *Main> s
""
[-1: test.hs:2:15-20] *Main>
It lets you step around in the evaluation history, highlights the actual expression that raised the exception (bold rather than starred on a terminal), and lets you inspect the local variables.
Another option is to recompile with profiling and some flags to tag appropriate cost centers, and run with the -xc profiling option which prints the cost center stack on uncaught exceptions
http://www.haskell.org/ghc/docs/latest/html/users_guide/prof-time-options.html
> ghc -prof -auto-all test.hs
> ./test +RTS -cs
1
2
... snipped 3 through 55 ...
56
*** Exception (reporting due to +RTS -xc): (THUNK_2_0), stack trace:
Main.foo,
called from Main.main,
called from Main.CAF
--> evaluated by: Main.main,
called from Main.CAF
test: Prelude.read: no parse
The reason this is a bit difficult is described a bit earlier on the debugger page
http://www.haskell.org/ghc/docs/latest/html/users_guide/ghci-debugger.html#tracing
Basically, efficient Haskell execution doesn't use anything resembling a normal call stack, so to get that kind of information on an exception you have to be running in some special mode (debugging or profiling) which does keep that sort of information.