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?

+3


source to share


1 answer


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.

+6


source







All Articles