我无法弄清楚为什么我会在以下代码中获得“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:编辑以提供更简单的代码示例
答案 0 :(得分:2)
由于你不能写
的原因,这个失败了 eval :: ExpQ -> Int
eval expr = $expr
因为它需要在运行时进行编译。
一种解决方案是通过返回嵌套findTransforms
表达式的表达式而不是所述表达式的值来使if
编译时间。
findTransforms :: Int -> [ExpQ] -> ExpQ
findTransforms _ [] = [| False |]
findTransforms e (r:rs) = [| if $r e == 1 then True else $(findTransforms e rs) |]
当然,这意味着当你想使用它时你必须拼接它。
答案 1 :(得分:1)
我不是Template Haskell的专家,但我认为r
($r
)的拼接必须在编译时发生,因此r
必须在编译时,r
是findTransforms
的运行时参数。
答案 2 :(得分:0)
阶段限制意味着您无法使用模板haskell 在它定义的同一模块中。如果你应该没问题 你把它放在一个模块中,然后从另一个模块调用它。
Dave4420是对的,这是关于编译的;你的模板haskell 必须在使用之前进行编译,因此必须在导入的模块中进行定义。 (这意味着在编译模块时ghc不需要额外的通过。)