GHC重寫assert
時優化只是id
。或者,它的行爲可以通過編譯器標誌來改變。不過,我注意到trace
也沒有發生同樣的情況。如果標誌未被設置或被設置,是否有trace
的版本,最終結果爲id
?像「assert」一樣優化「跟蹤」?
更一般地說,是否有方法根據用於編譯調用模塊的編譯器標誌(而不是用於編譯自身的標誌)來改變函數的行爲。就像assert
一樣。或者這是GHC的魔法,只能發生在assert
?
GHC重寫assert
時優化只是id
。或者,它的行爲可以通過編譯器標誌來改變。不過,我注意到trace
也沒有發生同樣的情況。如果標誌未被設置或被設置,是否有trace
的版本,最終結果爲id
?像「assert」一樣優化「跟蹤」?
更一般地說,是否有方法根據用於編譯調用模塊的編譯器標誌(而不是用於編譯自身的標誌)來改變函數的行爲。就像assert
一樣。或者這是GHC的魔法,只能發生在assert
?
不,至少不是基於assert
。 assert
的神奇作用於另一個方向,並用斷言取代身份函數。
-- Assertion function. This simply ignores its boolean argument. -- The compiler may rewrite it to @('assertError' line)@. -- | If the first argument evaluates to 'True', then the result is the -- second argument. Otherwise an 'AssertionFailed' exception is raised, -- containing a 'String' with the source file and line number of the -- call to 'assert'. -- -- Assertions can normally be turned on or off with a compiler flag -- (for GHC, assertions are normally on unless optimisation is turned on -- with @[email protected] or the @[email protected] -- option is given). When assertions are turned off, the first -- argument to 'assert' is ignored, and the second argument is -- returned as the result. -- SLPJ: in 5.04 etc 'assert' is in GHC.Prim, -- but from Template Haskell onwards it's simply -- defined here in Base.lhs assert :: Bool -> a -> a assert _pred r = r
警告:我沒有嘗試這樣做......
你可以用編譯器標誌完全取代Debug.Trace
模塊。請與功能瑣碎實現另一個模塊中Debug.Trace
:
module NoTrace (trace) where:
trace :: String -> a -> a
{-# INLINE trace #-}
trace _message = id
...
把這個模塊在一個名爲no-trace
另一個包。
將Debug.Trace
模塊隱藏在ghc的參數中including every module從基本包中除外Debug.Trace
。將Debug.Trace
替換爲no-trace
包中的NoTrace
。
ghc -package="base (Control, Control.Applicative, ..., Data.Word, Foreign, ...)" \
-package="no-trace (NoTrace as Debug.Trace)" \
...
在此之前使用的是改變了序幕,以取代一個有rewrite rules刪除trace
S中的前奏編譯器標誌的瘋狂的想法,但這些重寫規則將玷污任何進口模塊與他們一起編譯,即使下游進口商仍想使用痕跡。在查找如何替換前奏時,我發現ghc可以替代任何模塊。
好吧,回到我的電腦,最後想起我想演示這個。這裏所說:
import Control.Exception
import Debug.Trace
import Control.Monad
traceDebug :: String -> a -> a
traceDebug msg = assert (trace msg True)
main :: IO()
main = replicateM_ 2 $ do
print $ traceDebug "here1"()
print $ traceDebug "here2"()
print $ traceDebug "here3"()
當沒有優化編譯,輸出爲:
here1
()
here2
()
here3
()
()
()
()
隨着優化:
()
()
()
()
()
()
所以我覺得這個地址的要求,與各地標準告誡trace
一旦thunk被評估過,它將不會被第二次評估(這就是爲什麼這些消息只發生在第一次通過do
-block)。
我一直在回答這樣的問題。 「我不知道一種方式」並不是一個真正的答案,但如果沒有人願意說出來,那麼你根本就沒有迴應...... –
GHC做了一些單獨的編譯。如果定義模塊沒有展示展開,則調用模塊將被粘貼目標代碼。 – dfeuer
現在不在我的計算機上,但是如何在呼叫中追蹤呼叫並讓整個斷言得到優化呢? –