当优化为assert
时,GHC会重写id
。或者,可以使用编译器标志更改其行为。但是,我注意到trace
没有发生同样的情况。如果没有或已设置标志,是否有trace
的版本最终为id
?
更一般地说,有没有办法根据用于编译调用模块的编译器标志(而不是用于编译自身的标志)来改变函数的行为。很像assert
。或者这种GHC魔法是否只能在assert
发生?
答案 0 :(得分:9)
警告:我没试过这个......
您可以使用编译器标志完全替换Debug.Trace
模块。使用Debug.Trace
中的函数的简单实现创建另一个模块:
module NoTrace (trace) where:
trace :: String -> a -> a
{-# INLINE trace #-}
trace _message = id
...
将此模块放在另一个名为no-trace
的包中。
Debug.Trace
除Debug.Trace
之外的基本包中的including every module的ghc参数中隐藏Debug.Trace
模块。将NoTrace
替换为no-trace
包中的ghc -package="base (Control, Control.Applicative, ..., Data.Word, Foreign, ...)" \
-package="no-trace (NoTrace as Debug.Trace)" \
...
。
trace
这来自于使用编译器标志的疯狂想法,该标志改变了前奏,用一个rewrite rules替换prelude来删除var myDiv = document.querySelectorAll('.cls')[0];
myDiv.style.background='green'
s,但这些重写规则会污染导入的任何内容用它们编译的模块,即使下游导入器仍然想要使用跟踪。在查找如何替换前奏时,我发现ghc可以代替任何模块。
答案 1 :(得分:6)
不,至少不是基于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 @-O@ or the @-fignore-asserts@ -- 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
答案 2 :(得分:5)
好的,回到我的电脑,最后还记得我想证明这一点。这是:
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
- 阻止)。