2013-10-30 58 views
69

我需要將編譯腳本中的一些信息傳遞給模板Haskell。目前編譯腳本會將這些信息保存在系統環境中,所以我只是用System.Environment.getEnvironment來讀取它,它們包含在runIO中。有沒有更好的方法,比如將一些參數傳遞給ghc(類似於C預處理器的-D...),或者可能是TH中專門爲此設計的一些參數?如何正確地將編譯時信息傳遞給模板Haskell函數?

+9

從外部文件中讀取該信息並使用['addDependentFile'](http://hackage.haskell.org/package/template-haskell-2.8.0.0/docs/Language-Haskell-TH-Syntax。 html#v:addDependentFile)使'ghc --make'知道該文件是一個明顯的選擇。目前的計劃有哪些問題? –

+2

@MikhailGlushenkov實際上,環境只傳遞項目目錄的根目錄,然後從文件中讀取更多信息。所以'addDependentFile'將對我的情況有所幫助。目前的方案正在起作用,我只是想知道是否有其他的,規範的方式如何去做。 –

+5

您也可以使用['location'](http://hackage.haskell.org/package/template-haskell-2.8.0.0/docs/Language-Haskell-TH-Syntax.html#v:location)功能獲取項目目錄的根目錄(假設您知道從當前模塊到根目錄的相對路徑)。這裏是[示例](https://gist.github.com/23Skidoo/6258379)。 –

回答

3

它看起來像你要做的here,ghc中的-D選項似乎定義了一個編譯時間變量。

在這裏,在同一主題是question,似乎也回答你的問題的其他部分。 從我可以告訴,做條件編譯,你這樣做:

#ifdef MACRO_NAME 
    //Do stuff here 
    #endif 
+1

正如我在評論中所說的,我不想使用CPP和條件編譯。我沒有用處,我只想將信息傳遞給模板哈斯克爾。 '-D'選項會很好,如果在沒有CPP的情況下如何在TH中讀取它的話。 –

+1

同樣,這是用於* haskell *代碼中的條件編譯。除了使用-D定義宏(除了可能設置了一些值)之外,我不知道任何東西,然後您可以檢查haskell中的值,它可能工作。儘管如此,我對哈斯克爾知之甚少。 – jaked122

10

因爲很多人都感興趣的問題,我將添加我目前的做法,也許有人會覺得它有用。如果TH允許在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 [email protected] 
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 @[email protected] 
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打印Nothing;
  • DEBUG="yes" runhaskell Main.hs打印Just "yes"
相關問題