Looking at the description for traceIO
, I feel that it does exactly what hPutStrLn stderr
does. However when I looked into its source code:
traceIO :: String -> IO ()
traceIO msg = do
withCString "%s\n" $ \cfmt -> do
-- NB: debugBelch can't deal with null bytes, so filter them
-- out so we don't accidentally truncate the message. See Trac #9395
let (nulls, msg') = partition (=='\0') msg
withCString msg' $ \cmsg ->
debugBelch cfmt cmsg
when (not (null nulls)) $
withCString "WARNING: previous trace message had null bytes" $ \cmsg ->
debugBelch cfmt cmsg
It seems it uses a foreign routine called debugBelch
, which I failed to find any documentation about. So what does traceIO
do that can't be done by hPutStrLn stderr
?
One thing I can think of is that it might ensure that the string is printed as a unit, without any other trace messages inside. Indeed an experiment seems to confirm this:
Prelude Debug.Trace System.IO> traceIO $ "1" ++ trace "2" "3"
2
13
Prelude Debug.Trace System.IO> hPutStrLn stderr $ "1" ++ trace "2" "3"
12
3
Another difference is that it seems to remove characters that cannot safely be printed to stderr:
Prelude Debug.Trace System.IO> hPutStrLn stderr "\9731"
*** Exception: <stderr>: hPutChar: invalid argument (invalid character)
Prelude Debug.Trace System.IO> traceIO "\9731"
Prelude Debug.Trace System.IO>
As @dfeuer reminds me of, none of these features would be impossible to write in Haskell. So the deciding factor is probably this: debugBelch
is already a predefined C function, used all over the place in GHC's runtime system, which is written in C and C--, not Haskell.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With