I will hit though TH may be difficult to debug without seeing more code.
Let's look at an example code:
foo.hs:
{-
Now we can run this in GHCi (I am in version 7.0.2, which comes with the current Haskell platform):
$ ghci foo.hs -XTemplateHaskell *Main> :m +Language.Haskell.TH *Main Language.Haskell.TH> runQ (baz 2) <interactive>:1:7: No instance for (Language.Haskell.TH.Syntax.Lift (a0 -> a0)) arising from a use of `baz' Possible fix: add an instance declaration for (Language.Haskell.TH.Syntax.Lift (a0 -> a0)) In the first argument of `runQ', namely `(baz 2)' In the expression: runQ (baz 2) In an equation for `it': it = runQ (baz 2) *Main Language.Haskell.TH> runQ (bez 2) <interactive>:1:7: No instance for (Language.Haskell.TH.Syntax.Lift (a0 -> a0)) arising from a use of `bez' Possible fix: add an instance declaration for (Language.Haskell.TH.Syntax.Lift (a0 -> a0)) In the first argument of `runQ', namely `(bez 2)' In the expression: runQ (bez 2) In an equation for `it': it = runQ (bez 2) *Main Language.Haskell.TH> runQ (boz 2) LamE [VarP y_0] (InfixE (Just (LitE (IntegerL 2))) (VarE GHC.Num.+) (Just (VarE y_0))) *Main Language.Haskell.TH> runQ (byz 2) AppE (VarE Main.g) (LitE (IntegerL 2))
Here I tried to use runQ to see what TH splicing looks like for each of my functions in the sample code. It does not work on baz and bez , but it works for boz and byz .
Looking at TH for boz and byz , we see how the functions are removed: boz basically refers only to + by name (in VarE GHC.Num.+ ), And byz is just referring to g by name (in VarE Main.g )
For baz and bez this option is not listed in the table: both of these functions try to merge f , which is locally connected; therefore, a reference to VarE f does not make sense outside of baz and bez .
So what should a developer do? In short, instead of trying [| f |] [| f |] , you need to write an expression for f in the elevator directly in terms of identifiers that will be connected where the splice occurs.
On the side of the note, it is very easy to write Lift instances for algebraic data types, since you can always raise globally defined functions. Here is one for Maybe :
instance Lift a => Lift (Maybe a) where lift Nothing = [| Nothing |] lift (Just a) = [| Just a |]
intoverflow
source share