2012-04-04 1 views
4

準引用符を使用すると、コンパイル時にASTコードを生成できますが、生成されたコードは準引用符が書き込まれた場所に挿入されます。任意の方法で、コンパイル時に生成されたコードを他の場所に挿入することは可能ですか?例えば、QQが書かれたものとは異なる特定のモジュールファイルでは?ハードコーディングされたモジュール構造に依存しますが、それは問題ありません。Haskellのコンパイル時に別の場所にコードを含めるには?

これはQQでは不可能だが、誰かがそれを達成する別の方法を知っているなら、私は提案があります。

+4

あなたがこれで達成しようとしていることを言えば助けになると思います。技術的には、THはコンパイルされているモジュールの読み込みや解析を含む任意のIOを実行できるため、異なる場所や異なるモジュールから物を取り込むことができますが、詳細は実行しようとしていることに依存します。 – hammar

答えて

4

これに答えるには、準引用符が何であるかを知ることが役に立ちます。 GHC Documentationから、準クォータは、式のテンプレートHaskellの表現である、ExpQPatQTypeQ、及びDecQの1つ以上に任意の文字列からパーサの、ある

data QuasiQuoter = QuasiQuoter { quoteExp :: String -> Q Exp, 
           quotePat :: String -> Q Pat, 
           quoteType :: String -> Q Type, 
           quoteDec :: String -> Q [Dec] } 

の値であります、パターン、型、および宣言をそれぞれ示します。

擬似引用符を使用すると、GHCはパーサーを文字列に適用してExpQ(または他の型)を作成し、結果のテンプレートhaskell式をスプライスして実際の値を生成します。

TH式にアクセスできるように、quasiquoteの解析とスプライシングを分離することをお勧めします。次に、その式を別のモジュールにインポートして、そこにスプライスすることができます。

準引用符のタイプを知っていれば、これが可能であることは容易にわかります。通常は

-- file Expr.hs 
eval :: Expr -> Integer 
expr = QuasiQuoter { quoteExp = parseExprExp, quotePat = parseExprPat } 

-- file Foo.hs 
import Expr 
myInt = eval [expr|1 + 2|] 

としてQQを使用する代わりに、あなたは、パーサを自分で抽出TH表現を取得し、後でそれをスプライスすることができます:もちろん

-- file Foo.hs 
import Expr 

-- run the QQ parser 
myInt_TH :: ExpQ 
myInt_TH = quoteExp expr "1 + 2" 

-- file Bar.hs 
import Foo.hs 

-- run the TH splice 
myInt = $(myInt_TH) 

をあなたはこのすべてを自分で書いている場合は、準引用符をスキップし、パーサとTemplate Haskellを直接使用することができます。それはいずれの方法でもほとんど同じことです。

関連する問題