Up to now I have always worked with imperative languages like Pascal, C, C++, Java in a production environment, so I have experience with debuggers for these languages (Turbo Pascal, Turbo C, GDB / DDD, Visual Studio, Eclipse).
A debugger for an imperative language normally allows to
- Set break points on statements, and execute the program until the next break point is encountered.
- Execute the program one statement at a time, with the option of entering a function / method call or skipping over to the following statement.
When program execution is paused, one can examine the current state of the program, i.e.:
- Inspect the contents of the stack to see the current nesting of function calls.
- Inspect local variables, actual function parameters, global variables, and so on.
Since I have never worked with a functional programming language in a production environment, I was trying to figure out how a debugger for such a language would look like. For example:
- How does the debugger walk through the program if there are no statements like in an imperative language? Where does one set break points?
- In a language with lazy evaluation like Haskell, the sequence of function calls can be different from that of an eager language: will this make a big difference when trying to understand the call stack?
- What about variables? Since there is no state, I imagine that a debugger will only show the variable bindings for the current scope (?), i.e. there will be no local or global variables changing value as I step through the program.
Summarizing, are there any general, common features of functional-language debuggers that clearly distinguish them from imperative-language debuggers?