4 ms·
1. There's the ghci debugger, though I don't know if it is practical (I don't use it myself). Alternatively, you can use Debug.Trace (or the http://hackage.has
by Peaker 15y ago
1. There's the ghci debugger, though I don't know if it is practical (I don't use it myself).
Alternatively, you can use Debug.Trace (or the http://hackage.haskell.org/packages/archive/TraceUtils/0.1.0.1/doc/html/Debug-TraceUtils.html http://hackage.haskell.org/packages/archive/TraceUtils/0.1.0... extension), which makes "print-based" debugging easier than in imperative languages:
Say you have:
processValue f =
after .
map f .
before
If you want "print-based" debugging, you can use Trace.Utils.traceAround:
processValue f =
traceAround "processValue" $
after .
map f .
before
Or, if you just want the results of "after":
processValue f =
traceId "Result of after: " .
after .
map f .
before
Alternatively, there's also the FileLocation package, which gives you filenames + line numbers in your debug prints via Template Haskell macros.
2. Controlling evaluation is indeed tricky. Haskell programmers take manipulation of infinite data structures (of any kind) for granted -- but then if they want to control stack use, it gets a bit tricky. Other languages take stack use management for granted, but if you want to have infinite arbitrary data structures, it gets tricky.
I personally prefer Haskell's choice, because it means that having infinite structures doesn't contaminate the code with effects (which explicit suspensions/resumptions of computations would do), but it could probably be done better (e.g: move laziness/strictness annotations mostly to the type-level).