当前位置: 首页 > 知识库问答 >
问题:

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

安建木
2023-03-14

我需要将一些信息从编译脚本传递到模板Haskell中。目前编译脚本将信息保存在系统环境中,所以我只是使用system读取它。环境getEnvironment包装在runIO中。是否有更好的方法,例如将一些参数传递给ghc(类似于C预处理器的-D..),或者可能是专门为此设计的方法?

共有2个答案

羊舌新荣
2023-03-14

看起来就像您在这里要做的,ghc中的-D选项似乎定义了一个编译时变量。

在这里,关于同一主题的一个问题似乎也回答了你问题的另一部分。据我所知,要进行条件编译,您需要执行以下操作:

    #ifdef MACRO_NAME
    //Do stuff here
    #endif
沈飞翼
2023-03-14

既然有这么多人对这个问题感兴趣,我将添加我目前的方法,也许有人会发现它很有用。最好的方法可能是允许读取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

它可以这样使用:

{-# LANGUAGE TemplateHaskell #-}
import THEnv
main = print $( lookupCompileEnvExp "DEBUG" )

然后:

  • runhaskell Main。hs打印无任何内容
  • DEBUG=“yes”runhaskell Main。hs只打印“是”
 类似资料:
  • 如果需要与特定的应用编程接口/硬件组件交互,您将如何将信息从Flutter传递回Android/Native代码? 是否有任何事件通道可以以其他方式或类似于回调的方式发送信息? platform_channel文档指出,“方法调用也可以反向发送,平台充当Dart中实现的方法的客户端。quick_actions插件就是一个具体的例子。”在这种情况下,我看不出本机是如何接收到来自Flatter的消息的

  • 问题内容: 尝试访问传递给模板的函数时出现错误: 有人可以让我知道我在做什么错吗? 模板文件(struct.tpl): 调用文件: 这是用于生成struct样板代码的程序(以防万一有人想知道为什么我要在模板中这样做)。 问题答案: 自定义函数需要在解析模板之前进行注册,否则解析器将无法分辨标识符是否为有效的函数名。模板被设计为可静态分析的,这是必需的。 您可以先使用创建一个新的未定义模板,并且除了

  • 如何将 RelayState 正确传递到 Okta 端 ACS URL,以便它到达输入的 IdP? 我把 在 ACS URL 上,IdP 得到一个 SAMLRequest,中继状态为 哪个解码为 . 如果我把<代码>?RelayState=相反,如我所料,带有SAMLRequest的RelayState为空。 我附上了NetworkData.xml这是从Internet Explorer捕获的。在

  • 它给了我一个错误 我已经搜索了一些答案,但无法解决它。 这是我对这段代码的看法,我将视为指针,编译器分配五个内存并为userInput分配一个,然后我将这个地址(我知道java是)传递给class构造函数,我认为字段得到了地址值。 这就是我的理解,我错了吗?

  • 我有一个自定义函数,我想在刀片模板中传递它。这里是功能: 用法如下: 是否可以将自定义功能传递给刀片模板?非常感谢。

  • 我知道接受参数和,所以我已经尝试了2次(失败)来包装函数和args...: a.创建一个C样式的函数,该函数将调用传递给它的对象: 这会在GCC 4.8.5中导致以下错误: /usr/include/c++/4.8.2/functional:在'struct std::_bind_simple(std::_placeholder<1>,int))(int*)>>()>'的实例化中:/usr/inc