查看traceIO
的说明,我觉得它与hPutStrLn stderr
完全相同。但是,当我查看其源代码时:
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
它似乎使用了一个名为debugBelch
的外部例程,我没有找到任何文档。那么traceIO
可以做什么hPutStrLn stderr
呢?
答案 0 :(得分:4)
我能想到的一件事是它可以确保字符串作为一个单元打印,而不会在其中包含任何其他跟踪消息。事实上,一项实验似乎证实了这一点:
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
另一个区别是它似乎删除了无法安全打印到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>
正如@dfeuer提醒我的那样,这些功能都不可能在Haskell中编写。因此决定因素可能就是:debugBelch
已经是预定义的C函数,在GHC的运行时系统中使用all over the place,它是用C和C--编写的,而不是Haskell。