Вопрос

I could not figure out why I am getting "GHC stage restriction" in the following code:

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

(Do not worry if code does not make anything useful - it is extracted minimal example obfuscated for clarity).

I do not call any functions from spliced code. Why stage restriction?

EDIT1: edited to give even simpler code example

Это было полезно?

Решение

This fails for the same reason you can't write

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

because it would require compilation at run-time.

One solution is to make findTransforms compile-time as well by returning an expression of nested if expressions rather than the value of said expression.

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

Of course, this means that you'll have to splice it when you want to use it.

Другие советы

I am not an expert on Template Haskell, but it looks to me that the splicing of r ($r) must happen at compile-time, therefore r must be known at compile-time, but r is a run-time parameter to findTransforms.

Stage restriction means you can't use your template haskell in the same module in which it's defined. You should be OK if You put this in one module and call it from another module.

Dave4420 is right that this is about compilation; your template haskell must be compiled before it is used, so has to be defined in an imported module. (This means ghc doesn't need an extra pass when compiling the module.)

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top