Search code examples
haskellmonadsunsafe-perform-io

How do use putStrLn for tracing (Haskell)


I am trying to get a Haskell function to show whenever it is applied by adding a call to "putStrLn":

isPrime2 1 = False

isPrime2 n = do
    putStrLn n
    null (filter (==0) (map (mod n) (filter isPrime2 [2..(floor (sqrt(fromIntegral (n-1))))])))

(The ultimate goal is to demonstrate why one version of isPrime is more efficient than another.)

When I load the above code into GHCi, I get the error:

Couldn't match expected type Bool with actual type m0 b0

I'm sure this is a n00b mistake. Could someone tell me the right way to accomplish what I'm trying to do?


Solution

  • The problem is, that Haskell has a strict distinction between pure functions such as (+) and map and impure actions such as putStrLn and main. A pure function is supposed to always yield the same result when given the same input and not modifying anything. This obviously prohibits uses of PutStr and friends. The type system actually enforces this separation. Each function that does IO or is impure in any way has an IO sticking in front of it's type.


    tl;dr; use trace from the module Debug.Trace:

    import Debug.Trace
    
    isPrime2 1 = False
    isPrime2 n = show n `trace` null (filter (==0) (map (mod n) (filter isPrime2 [2..(floor (sqrt(fromIntegral (n-1))))])))
    

    But beware that the results may be rather surprising as there is no guarantee that your code will actually run; the argument of trace may run once or twice or any other number of times.