Testing functions via I / O in Haskell
I play codebags to sharpen my Haskell skills and face a problem I didn't have in imperative languages.
Let's say I'm writing a foo () function in javascript that takes an int, adds two, produces a square, subtracts one, and returns the square root of that number.
var foo = function(n) {
n += 2;
n = n * n;
n -= 1;
n = Math.sqrt(n);
}
I want to check the state of the data being processed in a function at various points to help me troubleshoot / revise / debug the code, so I will embed console.log () statements whenever I want to see where I am at. For example, am I really squaring the sum of n + 2 correctly halfway through the function? We'll see...
var foo = function(n) {
n += 2;
n = n * n;
console.log("n = " + n);
n -= 1;
n = Math.sqrt(n);
}
For now, this example should be simple enough so that Haskeller can write on one line if you have a complex function and want to check the state at different points, how do Haskellers do? Is there a standard practice using the IO () monad? Do they get around it in some other way?
source to share
GHCi has a fancy debugger that lets you loop through your code and evaluate it line by line, checking its status and intermediate results.
But of course there is also printf
-line debugging you are asking for using a function trace
from Debug.Trace
. There is nothing wrong with using this for small scripts imho, but it is usually discouraging.
trace
is of type String -> a -> a
, so you pass the string that is printed (through unsafePerformIO
) and any argument that just returns.
In your example, we could use it like this. This is your function translated to Haskell:
foo x = sqrt $ (x+2)**2 - 1
Now we can just add the trace
line we want to see, for example. "Debug Me: " ++ (show ((x+2)**2))
... First import Debug.Trace
though:
import Debug.Trace
foo x = sqrt $ (trace ("Debug Me: " ++ (show ((x+2)**2))) ((x+2)**2)) - 1
A little ugly? Following David Yoon below, we are better off using traceShowId :: Show a => a -> a
if what we want to output is identical to the intermediate output (converted to of course String
):
import Debug.Trace
foo x = sqrt $ (traceShowId ((x+2)**2)) - 1
See here for a summary of the debug options.
source to share