Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何正确地将编译时信息传递给模板Haskell函数?_Haskell_Compile Time_Template Haskell - Fatal编程技术网

如何正确地将编译时信息传递给模板Haskell函数?

如何正确地将编译时信息传递给模板Haskell函数?,haskell,compile-time,template-haskell,Haskell,Compile Time,Template Haskell,我需要将一些信息从编译脚本传递到模板Haskell中。目前编译脚本将信息保存在系统环境中,所以我只是使用system.environment.getEnvironment包装在runIO中来读取它。是否有更好的方法,例如将一些参数传递给ghc(类似于C预处理器的-D..),或者是专门为此目的而设计的某种方法?看起来就像您要做的,ghc中的-D选项似乎定义了一个编译时变量 在这里,关于同一主题的一个例子似乎也回答了你问题的另一部分。 据我所知,要进行条件编译,您可以执行以下操作: #ifd

我需要将一些信息从编译脚本传递到模板Haskell中。目前编译脚本将信息保存在系统环境中,所以我只是使用
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
  • DEBUG=“yes”runhaskell Main.hs
    只打印“yes”

从外部文件读取该信息,并使用将该文件告知ghc--make是一种明显的替代方法。当前方案存在哪些问题?@MikhailGlushenkov实际上,环境只传递项目目录的根目录,然后从文件中读取更多信息。因此,
addDependentFile
将对我的案例有所帮助。当前的方案正在运行,我只是想知道是否有其他一些规范的方法可以做到这一点。您还可以使用该函数获取项目目录的根目录(假设您知道当前模块到根目录的相对路径)。这里是。您可以将-XCPP与模板haskell一起使用,但您的方式似乎更好。您是否希望有人让用户选择自己的配置文件,例如,通过在命令行传递文件路径?正如我在评论中所说,我不想使用CPP和条件编译。我不需要它,我只想把信息传递给模板Haskell。如果有一种方法可以在没有CPP的情况下在TH中读取,那么
-D
选项将非常好。同样,这是用于haskell代码中的条件编译。我只知道用-D定义宏(可能有一些值集),然后检查haskell中的值,这可能会起作用。不过我对哈斯克尔的了解还不够确定。
{-# LANGUAGE TemplateHaskell #-}
import THEnv
main = print $( lookupCompileEnvExp "DEBUG" )