4

次のコードで「GHCステージ制限」が発生する理由がわかりませんでした。

import Language.Haskell.TH

rules :: [ExpQ]
rules = [ [| \a -> a |], [| \_ -> 1 |] ]

findTransforms :: Int -> [ExpQ] -> Bool
findTransforms _ [] = False
findTransforms e (r:rs) = if ($r e) == 1 then True else findTransforms e rs

(コードが何も役に立たない場合でも心配しないでください-明確にするために難読化された最小限の例が抽出されています)。

スプライスされたコードから関数を呼び出すことはありません。なぜステージ制限?

EDIT1:さらに簡単なコード例を提供するために編集

4

3 に答える 3

2

これはあなたが書くことができないのと同じ理由で失敗します

 eval :: ExpQ -> Int
 eval expr = $expr

実行時にコンパイルする必要があるためです。

1つの解決策は、ネストされた式の値ではなく、findTransformsネストされた式の式を返すことによって、コンパイル時も作成することです。if

findTransforms :: Int -> [ExpQ] -> ExpQ
findTransforms _ []     = [| False |]
findTransforms e (r:rs) = [| if $r e == 1 then True else $(findTransforms e rs) |]

もちろん、これはあなたがそれを使いたいときにそれをつなぎ合わせる必要があることを意味します。

于 2012-09-29T08:36:07.957 に答える
1

私はTemplateHaskellの専門家ではありませんが、r$r)のスプライシングはコンパイル時にr行われる必要があるため、コンパイル時に認識される必要がありますrが、の実行時パラメーターfindTransformsです。

于 2012-09-29T07:41:56.173 に答える
0

ステージ制限とは、テンプレートhaskellが定義されているのと同じモジュールで使用できないことを意味します。これを1つのモジュールに入れて、別のモジュールから呼び出すと、問題ありません。

Dave4420は、これがコンパイルに関するものであることは正しいです。テンプレートhaskellは、使用する前にコンパイルする必要があるため、インポートしたモジュールで定義する必要があります。(これは、モジュールをコンパイルするときにghcが追加のパスを必要としないことを意味します。)

于 2012-09-29T08:04:44.077 に答える