Cli*_*ton 5 debugging haskell ghc
GHC assert在优化时重写s id.或者,可以使用编译器标志更改其行为.但是,我注意到同样的情况不会发生trace.是否有一个版本trace刚刚结束,id好像一个标志没有或被设置?
更一般地说,有没有办法根据用于编译调用模块的编译器标志(而不是用于编译自身的标志)来改变函数的行为.很像assert.或者这种GHC魔法是否只会发生assert?
警告:我没试过这个......
您可以Debug.Trace使用编译器标志完全替换模块.使用以下函数的简单实现创建另一个模块Debug.Trace:
module NoTrace (trace) where:
trace :: String -> a -> a
{-# INLINE trace #-}
trace _message = id
...
Run Code Online (Sandbox Code Playgroud)
将此模块放在另一个名为的包中no-trace.
Debug.Trace通过包含基础包中的每个模块来隐藏ghc参数中的模块Debug.Trace.替换Debug.Trace与NoTrace从no-trace包.
ghc -package="base (Control, Control.Applicative, ..., Data.Word, Foreign, ...)" \
-package="no-trace (NoTrace as Debug.Trace)" \
...
Run Code Online (Sandbox Code Playgroud)
这来自于使用编译器标志的疯狂想法,该标志改变了前奏,用一个具有重写规则来删除traces 的前缀替换前奏,但是这些重写规则会污染导入用它们编译的模块的任何内容,即使下游导入器仍然存在想用痕迹.在查找如何替换前奏时,我发现ghc可以替换任何模块.
不,至少不是基于assert.神奇的assert工作方向是另一个方向,并用断言取代身份功能.
这是assert基地4.9:
Run Code Online (Sandbox Code Playgroud)-- 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
好的,回到我的电脑,最后还记得我想证明这一点.开始:
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" ()
Run Code Online (Sandbox Code Playgroud)
在没有优化的情况下编译时,输出为:
here1
()
here2
()
here3
()
()
()
()
Run Code Online (Sandbox Code Playgroud)
通过优化:
()
()
()
()
()
()
Run Code Online (Sandbox Code Playgroud)
所以我认为这解决了请求,标准警告trace一旦thunk被评估,它将不会被第二次评估(这就是为什么消息只在第一次通过do-block时发生).