GHC stage limitation (Template Haskell)

I could not understand why I get the "GHC scene 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 ($re) == 1 then True else findTransforms e rs 

(Don’t worry if the code does nothing useful - it extracts a minimal example, confusing for clarity).

I do not call any functions from spliced ​​code. Why is there a limit on the scene?

EDIT1: edited to give an even simpler code example

+4
source share
3 answers

This is not possible for the same reason that you cannot write

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

because it will require compilation at runtime.

One solution is also to make findTransforms compile time by returning an expression of nested if expressions rather than the value of the specified expression.

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

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

+2
source

I'm not an expert on the Haskell pattern, but it seems to me that r ( $r ) splicing should happen at compile time, so r should be known at compile time, but r is the findTransforms runtime findTransforms .

+1
source

The script means that you cannot use your haskell template in the same module in which it is defined. You should be fine if you put this in one module and call it from another module.

Dave4420 is right that this is a compilation; your haskell template must be compiled before using it, so you need to define it in the imported module. (This means that ghc does not require an extra pass when compiling a module.)

0
source

Source: https://habr.com/ru/post/1436915/


All Articles