标签: template-haskell

为什么这个模板Haskell有效?

考虑以下代码:

magic :: String -> Q Exp
magic s = [e| putStrLn s |]

现在,尽我所知,这实际上不应该起作用.在牛津括号内,s不在范围内.然而,上述显然完美无缺.

如果我们稍微改变这个例子,它现在可怕地破坏了:

magic :: Exp -> Q Exp
magic (VarE n) = [e| putStrLn (nameBase n) |]

就像以前一样,我们有一个不在范围内的变量.而一次,它打破了.但它没有抱怨不在范围内的变量; 相反,它抱怨一些没有实例的无证件类.

谁知道到底发生了什么?

haskell template-haskell

4
推荐指数
1
解决办法
299
查看次数

导出模板haskell生成的定义

我的模块包含定义,其中一部分是导出的(在module子句中).我也想导出Template Haskell生成的声明.但由于似乎没有办法module用TH 修改条款,我不能这样做.

是否可以指定应该导出TH生成的声明?或者也许有其他方法可以做到这一点?

haskell code-generation template-haskell

4
推荐指数
1
解决办法
409
查看次数

如何在相对于正在编译的文件的文件上使用TemplateHaskell的addDependentFile?

我希望我的TemplateHaskell表达式(使用IO并依赖于MyDependency.txt文件)在更改该文件时重新计算.

因此,我正在使用addDependentFile "MyDependency.txt"告诉ghc在编译代码时检查该文件是否有修改.

不幸的是,这不起作用,因为addDependentFile只相对于调用ghc的目录起作用.

我如何使用它依赖于我正在编译的文件旁边(在同一目录中)的文件?

haskell template-haskell

4
推荐指数
1
解决办法
215
查看次数

如何允许在反引号中不仅嵌入值,还嵌入任意 haskell 表达式

最近,我学习了如何实现具有反引号功能的准引号,如printfQ下面的代码所示:

main = do
  let itemName = "apple"
      price = 1.29 
  [printfQ| The price of #{itemName} is #{price}. |]
Run Code Online (Sandbox Code Playgroud)

准引号的成分字符串将被传递到quoteExp printfQ :: String -> ExpQ. 所以我们要做的就是解析给定的String,找到要嵌入的名称"itemName""price"应用varE . mkName每个名称,并构建ExpQ.

现在假设我想扩展它printfQ以允许表达式嵌入,如下所示:

[printfQ| The price of #{itemNames !! i} is #{price + taxOf price}. |]

"itemNames !! i"我可以编写检测两个字符串和 的解析器"price + taxOf price"。但随后我需要一个更强版本的,这是一个将这些字符串转换为varE . mkName的函数,将它们解释为引用所使用的命名空间的表达式。String -> ExpQExpQprintfQ

我的问题:是否有任何库函数可以将此字符串转换为 AST?有一些简单的方法可以做到这一点,还是我需要编写整个 …

haskell quotations template-haskell

4
推荐指数
1
解决办法
277
查看次数

编写递归模板haskell函数

是否有可能将递归TH函数转换为将编译的等效形式?以下定义不起作用,因为为了编译fact,必须先编译fact.

fact :: ExpQ -> ExpQ
fact n = [|
    case $n of 
      1 -> 1
      _ -> $n * $(fact [| $n - 1 |]) |]
Run Code Online (Sandbox Code Playgroud)

这个简单的例子很容易解决(fact n = [| product [ 1.. $n] |])但是在一般情况下,如果不能将给定的函数重写为循环,是否可以定义递归TH函数?是否还有一个可行的例子?

为了澄清未来的读者:这个问题具体是关于编写递归 TH函数 - 而不是'如何拼接阶乘函数'.

我的问题的答案非常简单:

{-# LANGUAGE TemplateHaskell #-}

import Control.Monad.Fix (fix)
import Language.Haskell.TH

fact = [| \f x -> $([| 
     case x of 
       1 -> 1 
       _ -> f $([| x - 1 |]) * x …
Run Code Online (Sandbox Code Playgroud)

recursion haskell template-haskell

4
推荐指数
1
解决办法
331
查看次数

在不使用列表的情况下嵌入长字符串

对于几个项目,我需要将长字符串嵌入到Haskell源代码中.

显而易见的方法是unlines使用行列表.但是,阅读和维护这一过程非常麻烦.

cCode :: String
cCode = unlines [
          "int main(int argc*, char** argv)",
          "  doStuff();",
          "}"]
Run Code Online (Sandbox Code Playgroud)

有没有什么方法可以嵌入字符串而没有任何开销(如上面显示的列表)甚至文件?TemplateHaskell/Quasi-quotation是走这里的方式吗?

注意:此问题以问答形式回答.因此,它没有显示任何研究工作.

haskell template-haskell

4
推荐指数
1
解决办法
201
查看次数

为什么任意大小的元组有用?(模板Haskell)

Template Haskell介绍性文本中,模板Haskell有用的一个例子是使用任意大小的元组.

任意大小的元组的目的是什么?如果数据类型相同,为什么不使用列表?如果元组中的数据类型不同,如何将其扩展为任意大小?

haskell tuples list template-haskell

4
推荐指数
1
解决办法
368
查看次数

用镜头替换记录投影功能

几乎每次我做一个记录,我发现自己后来立即添加makeLenses ''Record(从镜头),我从来没有真正使用记录给我的投影功能.事实上,看看makeLenses产生什么(使用GHC -ddump-splices标志),看起来甚至不使用那些投影功能,除了为它产生的镜头选择一个名称.

有没有办法,通过TemplateHaskell或通过预处理器,或坦率地任何其他魔法,我可以得到记录投影功能直接Van Laarhoven镜头?

要明确,这意味着

data Record a b = Record { x :: a, y :: b }
Run Code Online (Sandbox Code Playgroud)

会生成(带type Lens s t a b = forall f. Functor f => (a -> f b) -> s -> f t)

x :: forall a b c. Lens (Record a b) (Record c b) a c
x f (Record _x _y) = fmap (\x' -> Record x' _y) (f …
Run Code Online (Sandbox Code Playgroud)

haskell ghc template-haskell

4
推荐指数
1
解决办法
270
查看次数

按值修改Haskell嵌套记录

说我有一个嵌套的结构,如下所示:

data Bar = Bar { _id :: Integer, _bars :: [Bar] }
data Foo = Foo { _bars :: [Bar] }
Run Code Online (Sandbox Code Playgroud)

我有Foo一堆Bars与各种ids 在一起:

foo = Foo [Bar 1 [Bar 2], Bar 3 [Bar 4, Bar 5]]
Run Code Online (Sandbox Code Playgroud)

怎么办,可能使用的镜头,我修改foo,从而Bar 5成为Bar 6

我知道我曾经fclabels做过这样的事情:

mkLabel ''Foo
mkLabel ''Bar
modify bars (\bars -> ...) foo
Run Code Online (Sandbox Code Playgroud)

但是条可以无限嵌套。如何找到并修改Bar具有指定ID的?

haskell records template-haskell lenses

4
推荐指数
1
解决办法
490
查看次数

Haskell:使准引用值严格/在编译时评估

我有一个“月”类型,大致是

\n\n
newtype Month = Month Word8\n
Run Code Online (Sandbox Code Playgroud)\n\n

Month构造函数未导出的地方;相反,一个函数

\n\n
mon :: Word8 -> Maybe Month\nmon i = if i > 0 && i < 13\n        then Just $ Month i\n        else Nothing\n
Run Code Online (Sandbox Code Playgroud)\n\n

被导出,仅当输入值在 1 和 12 之间(含 1 和 12)时才会返回一个值。

\n\n

现在,使用Language.Haskell.TH.Quote,我定义了一个准引用 ... 运算符?...这允许我“在编译时”“创建” Month 的实例:

\n\n
month :: QuasiQuoter\nmonth = QuasiQuoter { quoteDec  = error "quoteDec not implemented"\n                    , quoteType = error "quoteType not implemented"\n                    , quotePat  = "quotePat not implemented"\n                    , quoteExp = …
Run Code Online (Sandbox Code Playgroud)

haskell lazy-evaluation template-haskell quasiquotes

4
推荐指数
1
解决办法
275
查看次数