提升函数的实例?

时间:2011-03-14 04:13:09

标签: haskell

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

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

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

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

1 个答案:

答案 0 :(得分: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 |]

现在我们可以在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))

我在这里所做的是尝试使用runQ来查看示例代码中每个函数的TH拼接。它在bazbez上失败,但适用于bozbyz

查看bozbyz的TH,我们可以看到函数是如何解除的:boz基本上只是按名称引用+({{1} }}),而VarE GHC.Num.+只是按名称引用byz(在g中)。

对于VarE Main.gbaz,此选项不在表中:这两个函数都试图拼接bez,这是本地绑定的;因此,在fVarE f之外,对baz的引用是没有意义的。

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

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

Maybe