如何正确地将编译时信息传递给模板Haskell函数?
我需要将一些信息从编译脚本传递到模板Haskell中。目前编译脚本将信息保存在系统环境中,所以我只是使用如何正确地将编译时信息传递给模板Haskell函数?,haskell,compile-time,template-haskell,Haskell,Compile Time,Template Haskell,我需要将一些信息从编译脚本传递到模板Haskell中。目前编译脚本将信息保存在系统环境中,所以我只是使用system.environment.getEnvironment包装在runIO中来读取它。是否有更好的方法,例如将一些参数传递给ghc(类似于C预处理器的-D..),或者是专门为此目的而设计的某种方法?看起来就像您要做的,ghc中的-D选项似乎定义了一个编译时变量 在这里,关于同一主题的一个例子似乎也回答了你问题的另一部分。 据我所知,要进行条件编译,您可以执行以下操作: #ifd
system.environment.getEnvironment
包装在runIO
中来读取它。是否有更好的方法,例如将一些参数传递给ghc
(类似于C预处理器的-D..
),或者是专门为此目的而设计的某种方法?看起来就像您要做的,ghc中的-D选项似乎定义了一个编译时变量
在这里,关于同一主题的一个例子似乎也回答了你问题的另一部分。
据我所知,要进行条件编译,您可以执行以下操作:
#ifdef MACRO_NAME
//Do stuff here
#endif
既然有这么多人对这个问题感兴趣,我将添加我目前的方法,也许有人会发现它很有用。最好的方法可能是允许读取GHC命令行上的
-D
参数,但目前似乎没有实现类似的功能
一个简单的模块允许TH读取编译时环境。助手功能还允许读取文件;例如,从环境中读取配置文件的路径,然后读取该文件
{-# LANGUAGE TemplateHaskell #-}
module THEnv
(
-- * Compile-time configuration
lookupCompileEnv
, lookupCompileEnvExp
, getCompileEnv
, getCompileEnvExp
, fileAsString
) where
import Control.Monad
import qualified Data.Text as T
import qualified Data.Text.IO as T
import Language.Haskell.TH
import Language.Haskell.TH.Syntax (Lift(..))
import System.Environment (getEnvironment)
-- Functions that work with compile-time configuration
-- | Looks up a compile-time environment variable.
lookupCompileEnv :: String -> Q (Maybe String)
lookupCompileEnv key = lookup key `liftM` runIO getEnvironment
-- | Looks up a compile-time environment variable. The result is a TH
-- expression of type @Maybe String@.
lookupCompileEnvExp :: String -> Q Exp
lookupCompileEnvExp = (`sigE` [t| Maybe String |]) . lift <=< lookupCompileEnv
-- We need to explicly type the result so that things like `print Nothing`
-- work.
-- | Looks up an compile-time environment variable and fail, if it's not
-- present.
getCompileEnv :: String -> Q String
getCompileEnv key =
lookupCompileEnv key >>=
maybe (fail $ "Environment variable " ++ key ++ " not defined") return
-- | Looks up an compile-time environment variable and fail, if it's not
-- present. The result is a TH expression of type @String@.
getCompileEnvExp :: String -> Q Exp
getCompileEnvExp = lift <=< getCompileEnv
-- | Loads the content of a file as a string constant expression.
-- The given path is relative to the source directory.
fileAsString :: FilePath -> Q Exp
fileAsString = do
-- addDependentFile path -- works only with template-haskell >= 2.7
stringE . T.unpack . T.strip <=< runIO . T.readFile
然后:
打印runhaskell Main.hs
李>Nothing
只打印“yes”DEBUG=“yes”runhaskell Main.hs
addDependentFile
将对我的案例有所帮助。当前的方案正在运行,我只是想知道是否有其他一些规范的方法可以做到这一点。您还可以使用该函数获取项目目录的根目录(假设您知道当前模块到根目录的相对路径)。这里是。您可以将-XCPP与模板haskell一起使用,但您的方式似乎更好。您是否希望有人让用户选择自己的配置文件,例如,通过在命令行传递文件路径?正如我在评论中所说,我不想使用CPP和条件编译。我不需要它,我只想把信息传递给模板Haskell。如果有一种方法可以在没有CPP的情况下在TH中读取,那么-D
选项将非常好。同样,这是用于haskell代码中的条件编译。我只知道用-D定义宏(可能有一些值集),然后检查haskell中的值,这可能会起作用。不过我对哈斯克尔的了解还不够确定。
{-# LANGUAGE TemplateHaskell #-}
import THEnv
main = print $( lookupCompileEnvExp "DEBUG" )