Are there any nice ways to use Debug.Trace functions?
(it’s a bit of an oxymoron, I know!)
Small problem: if I insert them into my code, and want to uncomment them I usually also have to worry about whitespace again (maybe an auto formatter is a good idea).
Quite happy I have gone a long time without them, but they are handy also.
One trick I learned a while ago is to use ' to differentiate between traced function and untraced one. Say i have foo with some args and I want to debug it. I will change code from
foo ... = ... foo ... -- first pattern match, recursive call
foo ... = ... -- another pattern match
to
foo ... = traceShow (..., ..., ...) $ foo' ... -- put the arguments in the tuple and then call the original function
foo' ... = ... foo ... -- first pattern match, recursive call
foo' ... = ... -- another pattern match
This way, I don’t need to change te rest of the code and can quickly remove tracing by commenting the first line and removing the 's
I’m not sure it counts as nice but I often add debug and performance stuff in as (the lazy) StateT, and then you can flip between evalStateT for non-debug and runStateT for debug, without having to erase the debug code.
I’m new to Haskell coming from Python where I use print debugging frequently. I’m glad I found this page because there are some excellent suggestions here!
I often want to add a label to a traced value. Currently, I’m using this function:
debug :: Show a => String -> a -> a
debug label expr = trace (label ++ " " ++ show expr) expr
which can be used inline like this:
fac :: (Show t, Eq t, Num t) => t -> t
fac 0 = 1
fac n = debug "n" n * fac (n-1)
I really wish this function was defined in Debug.Trace.
{-# LANGUAGE BangPatterns #-}
fac :: (Show t, Eq t, Num t) => t -> t
fac 0 = 1
fac n = n * fac (n-1)
where !() = traceShow ("n", n) ()
This has at least two benefits over your debug: it doesn’t require defining a new debug combinator, and it’s a single line that can be added or deleted freely without changing the actual functional code.