提升功能实例? [英] Lift instance for a function?

查看:69
本文介绍了提升功能实例?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我需要将一个函数放入模板Haskell代码中.我正在使用表达式语法:

I need to put a function into Template Haskell code. I am using the expression syntax:

[|f|]

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

Some functions seem to work automatically. However, for this particular one I get the following erroe message:


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

我不知道如何为一个函数创建一个提升实例,并且似乎找不到任何有用的信息.谁能指出我的资源或让我大致了解这是如何实现的?同时,我将看看是否可以减少我的具体示例.

I have no idea how to make a lift instance for a function, and can't seem to find any useful information. Can anyone point me to a resource or give me an idea of how this is accomplished in general? In the mean time I will see if I can pare down my specific example.

推荐答案

尽管很难调试,而且看不到更多代码,但我会采取行动.

I'll take a stab, though TH can be hard to debug without seeing more code.

让我们看一些示例代码:

Let's take a look at some sample code:

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平台附带的版本):

Now we can fire this up in GHCi (I'm on version 7.0.2, which is what ships 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))

我在这里所做的尝试是使用runQ来查看示例代码中我的每个函数的TH接头的外观.在bazbez上失败,但在bozbyz上有效.

What I've done here is attempted to use runQ to see what the TH splice looks like for each of my functions in the sample code. It fails on baz and bez, but works for boz and byz.

查看bozbyz的TH,我们可以看到如何提升功能:boz基本上只是按名称(在VarE GHC.Num.+中)指代+,而byz只是通过名称(在VarE Main.g中)引用g.

Looking at the TH for boz and byz, we can see how functions are lifted: boz is basically just referring to + by name (in VarE GHC.Num.+), while byz is just referring to g by name (in VarE Main.g).

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

For baz and bez, this option isn't on the table: both of those functions are attempting to splice f, which is locally bound; hence, reference to VarE f wouldn't make sense outside of baz and bez.

那么开发人员要做什么?简而言之,您无需直接尝试[| f |],而是需要直接在升降机中编写f的表达式,这取决于将在发生拼接的位置绑定的标识符.

So what's a developer to do? In short, instead of trying [| f |], you need to write the expression for f in the lift directly, in terms of identifiers that will be bound where the splice occurs.

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

On a side note, it is very easy to write Lift instances for algebraic data types, since you can always lift globally-defined functions. Here's one for Maybe:

instance Lift a => Lift (Maybe a) where
  lift Nothing = [| Nothing |]
  lift (Just a) = [| Just a |]

这篇关于提升功能实例?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆