提升函数的实例?

Gre*_*ber 6 haskell

我需要将一个函数放入Template Haskell代码中.我使用的是表达式语法:

[|f|]
某些功能似乎自动运行.但是,对于这个特定的一个,我得到以下错误消息:

   No instance for (Lift (String -> [Content]))

我不知道如何为一个函数创建一个提升实例,似乎无法找到任何有用的信息.任何人都可以向我指出一个资源或者让我知道一般情况下这是如何实现的?与此同时,我将看看我是否可以削减我的具体例子.

int*_*low 7

虽然如果不看更多代码就很难调试TH,我会采取刺激措施.

我们来看看一些示例代码:

foo.hs:

{-# Language TemplateHaskell #-}

baz x = let f y = x + y
    in [| f |]

bez x = let f y = x + y
    in [| \y -> f y |]

boz x = [| \y -> x + y |]

g x y = x + y

byz x = [| g x |]
Run Code Online (Sandbox Code Playgroud)

现在我们可以在GHCi中解决这个问题(我的版本是7.0.2,这是当前Haskell平台附带的版本):

$ 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))
Run Code Online (Sandbox Code Playgroud)

我在这里所做的是尝试使用runQ示例代码中的每个函数来查看TH splice的样子.它未能对bazbez,但工程bozbyz.

看看TH for bozbyz,我们可以看到函数如何解除:boz基本上只是+通过名称(in VarE GHC.Num.+)byz引用,而只是g通过名称(in VarE Main.g)引用.

对于bazbez,此选项不在表中:这两个函数都试图拼接f,这是本地绑定的; 因此,VarE fbaz和之外的参考是没有意义的bez.

那么开发人员应该做些什么呢?简而言之,[| f |]您需要f直接在电梯中编写表达式,而不是在绑定发生的地方绑定标识符.

另一方面,Lift为代数数据类型编写实例非常容易,因为您始终可以提升全局定义的函数.这是一个用于Maybe:

instance Lift a => Lift (Maybe a) where
  lift Nothing = [| Nothing |]
  lift (Just a) = [| Just a |]
Run Code Online (Sandbox Code Playgroud)