Whenever you have these types of errors like Couldn't match expected type X with actual type Y , you should use a system like haskell to guide you.
So let's see what the problem is:
You have a pure function with type Int -> Bool . And you want to print some debug output that is clearly not clean (i.e. Which lives in IO Monad ).
But in any case, what you want to write is s.th. along these lines:
foo x | x > 0 = debug "ok" True | otherwise = debug "ohhh...no" False
However, your function type should be foo :: Int -> Bool
So, let's define a debug function that will satisfy type checking. He will have to take the line (your debug message) and Bool (your result) and only evaluate Bool.
debug :: String -> Bool -> Bool debug = undefined
But if we try to implement it, this does not work, since we cannot avoid IO Monad, since the type putStrLn is equal to putStrLn :: String -> IO () . To combine it with a grade on Bool , we also need to put Bool in the context of IO :
debugIO msg result = putStrLn msg >> return result
Ok, ask ghci about the type of this function:
Main> :t debugIO debugIO :: String -> b -> IO b
So, we get IO Bool , but you just need Bool for this.
Is there a function with type IO b -> b ? A quick hoogle search gives us a hint:
The infamous unsafePerformIO :: IO a -> a has the type we need here.
So now we can implement our debug function in terms of debugIO :
debug :: String -> Bool -> Bool debug sr = unsafePerformIO $ debugIO sr
which is actually what you get with the trace function in the Debug.Trace package, as FUZxxl already pointed out. <w> And since we agree that you should never use unsafePerformIO , the use of the trace function is preferred. Just keep in mind that in spite of this being a pure type signature, in fact it is also not referential transparent and uses unsafePerformIO under it.