2015-10-10 52 views
4

看看traceIO的描述,我覺得它確實是hPutStrLn stderr所做的。然而,當我看着它的源代碼:`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完成?

回答

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 

另一個不同之處是,它似乎要移除不能安全地打印到標準錯誤的字符:作爲@dfeuer讓我想起了,

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> 

沒有這些功能將無法在Haskell中編寫。所以決定因素可能是這樣的:debugBelch已經是預定義的C函數,在GHC的運行時系統中使用all over the place,它是用C和C--編寫的,而不是Haskell。

+0

難道不是'先評估$ force msg'才能避免干擾嗎? – dfeuer

+0

@dfeuer你是對的,這*可以直接從Haskell完成。它已經作爲C函數提供。我已經編輯了我的答案並附上了關於此的說明。 –