像“断言”一样使“跟踪”优化?

时间:2016-11-22 05:16:36

标签: debugging haskell ghc

当优化为assert时,GHC会重写id。或者,可以使用编译器标志更改其行为。但是,我注意到trace没有发生同样的情况。如果没有或已设置标志,是否有trace的版本最终为id

更一般地说,有没有办法根据用于编译调用模块的编译器标志(而不是用于编译自身的标志)来改变函数的行为。很像assert。或者这种GHC魔法是否只能在assert发生?

3 个答案:

答案 0 :(得分:9)

警告:我没试过这个......

您可以使用编译器标志完全替换Debug.Trace模块。使用Debug.Trace中的函数的简单实现创建另一个模块:

module NoTrace (trace) where:

trace :: String -> a -> a
{-# INLINE trace #-}
trace _message = id

...

将此模块放在另一个名为no-trace的包中。

Debug.TraceDebug.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)

不,至少不是基于assertassert的魔力适用于另一个方向,并用断言替换身份函数。

这是assert from base 4.9

-- 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 - 阻止)。