10

好的,这是一个简单的问题。我写了一个函数debug :: String -> IO ()。我想进行设置,以便当我以一种方式编译我的程序时,这个函数会写入标准错误,如果我以另一种方式编译我的程序,这个函数就会变成无操作。是否有一些简单的编译时切换来做到这一点?还是我必须自己实现一些东西?

4

3 回答 3

11

我不认为涉及trace是解决这个问题的正确方法。

相反,您可以使用预处理器来禁用/启用调试消息。将以下内容放在单独的文件中:

{-# LANGUAGE CPP #-}
import System.IO

debug :: String -> IO ()
debug message =
#ifdef DEBUG
  hPutStrLn stderr message
#else
  return ()
#endif

{-# LANGUAGE CPP #-}行为当前文件启用 C 预处理器。然后,您可以使用ghc -DDEBUG或仅使用ghc.

于 2013-05-19T09:51:29.837 回答
9

您可以使用 CPP 预处理器和#ifdef.

  1. 首先,使用#ifdef在函数的两个版本之间进行选择。

    {-# LANGUAGE CPP #-}
    module Logging (debug) where
    
    debug :: String -> IO ()
    #ifdef DEBUG
    debug = putStrLn
    #else
    debug _ = return ()
    #endif
    
  2. 然后,在您的文件中添加一个标志.cabal来控制它。

    ...
    
    flag debug
      description: Enable debug logging
      default:     False
    
    executable foo  -- or library
      if flag(debug)
        cpp-options:  -DDEBUG
    
      ...
    
  3. 最后,要启用调试,请-f在配置时启用标志:

    $ cabal configure -f debug
    
于 2013-05-19T09:51:51.880 回答
2

为了补充这里给出的优秀答案,我想提一下这种方法,以防人们(像我一样)使用最新版本stackhpack.

package.yaml文件中,我添加了以下内容:

  flags:
    debug: # Or whatever name you want to give to the flag
      description: Enable debug
       manual: True
       default: False

   when:
     - condition: flag(debug)
       cpp-options:  -DDEBUG

然后我建议将traceIOfromDebug.Trace与 结合使用NoTrace,这样在没有标志traceIO的情况下编译代码时将不起作用:debug

{-# LANGUAGE CPP #-}

-- ...

#ifdef DEBUG
import Debug.Trace
#else
import Debug.NoTrace
#endif              

-- ...
someFunc :: IO ()
someFunc = do
    -- ...
    traceIO "Whatever..."

使用堆栈时,debug可以使用以下--flag选项启用标志:

stack build --flag "your-package:debug"

或者,如果您正在测试您的包裹:

stack build --flag "your-package:debug"

如果hpack未使用,那么您可以按照 hammar的说明配置您的 cabal 文件。

于 2018-01-03T17:32:05.890 回答