Search code examples
haskellghctemplate-haskell

GHC stage restriction (Template Haskell)


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


Solution

  • 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.