Whenever you have these kinds of type errors like Couldn't match expected type X with actual type Y
you should use the haskell type system to guide you.
So let's see what is the problem:
You have a pure function with the type Int -> Bool
. And you want to print some debug output which is clearly not pure (i.e. which lives in the IO Monad).
But anyway what you want to write is s.th. along those lines:
foo x
| x > 0 = debug "ok" True
| otherwise = debug "ohhh...no" False
Still, the type of your function should be foo :: Int -> Bool
So let's define a debug
function that will satisfy the type-checker. It would have to take a String (your debug message) and a Bool (your result) and only evaluate to the Bool.
debug :: String -> Bool -> Bool
debug = undefined
But if we try to implement it, it kind of does not work since we can't escape the IO Monad since the type of putStrLn is putStrLn :: String -> IO ()
. In order to combine it with evaluating to a Bool
we will have to put the Bool
in the context of the IO
too:
debugIO msg result = putStrLn msg >> return result
Ok, let's ask ghci for the type of this function:
Main> :t debugIO
debugIO :: String -> b -> IO b
So we get an IO Bool
but would need just a Bool
.
Is there a function with the type IO b -> b
? A quick lookup on hoogle gives us a hint:
The infamous unsafePerformIO :: IO a -> a
has the type we need here.
So now we could implement our debug
function in terms of debugIO
:
debug :: String -> Bool -> Bool
debug s r = unsafePerformIO $ debugIO s r
which actually is pretty much what you get with the trace
function in the Debug.Trace
package as already pointed out by FUZxxl.
And since we agree that one should never use unsafePerformIO
the usage of the trace
function is preferred. Just keep in mind that despite it's pure type signature it actually is also not referential transparent and uses unsafePerformIO
underneath.
n
before taking its square root? That will only work for numbers that aren't squares of primes and will fail for, e.g., 25. – Headward