Raise instance for function?

I need to put a function in the Haskell template code. I use expression syntax:

  [| f |] 
Some functions work automatically. However, for this particular one, I get the following erroe message:
  No instance for (Lift (String -> [Content]))

I do not know how to make an instance of an elevator for a function and cannot find any useful information. Can someone point me to a resource or give me an idea of ​​how this is done in general? At the same time, I will see if I can fulfill my specific example.

+6
haskell
source share
1 answer

I will hit though TH may be difficult to debug without seeing more code.

Let's look at an example code:

foo.hs:

{-# Language TemplateHaskell #-} baz x = let fy = x + y in [| f |] bez x = let fy = x + y in [| \y -> fy |] boz x = [| \y -> x + y |] gxy = x + y byz x = [| gx |] 

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 |] 
+7
source share

All Articles