标签: template-haskell

Template Haskell声明中的局部变量

我正在阅读pozorvlak在Template Haskell上发布的婴儿步骤帖子,试图自己理解它,我发现了这一部分:

回想一下,我们试图以编程方式生成表单的声明data Fred = Fred.让我们用quasiquoting来试试吧.由于调用TH代码的限制,我们必须将它放在自己的模块中,所以让我们将以下内容放在Keyword.h中,以便编译器可以找到它:

module Keyword (keyword) where

import Language.Haskell.TH.Syntax
keyword name = [d| data $(name) = $(name) |]
Run Code Online (Sandbox Code Playgroud)

现在编译:

Prelude> :l Keyword.hs
[1 of 1] Compiling Keyword          ( Keyword.hs, interpreted )

Keyword.hs:6:24: parse error on input `$('
Run Code Online (Sandbox Code Playgroud)

这跟我打了个响铃,看起来和我最近读到的其他东西一样,模板Haskell包文档:

对于动态绑定的thing(NameS),我们可能希望它们以依赖于上下文的方式,因此我们再次不需要名称空间.例如:

let v = mkName "T" in [| data $v = $v |]
Run Code Online (Sandbox Code Playgroud)

这里我们Name对类型构造函数和数据构造函数使用相同的

嗯,这几乎是一样的,让我们看看我能不能这样做:

 module Example where
 import Language.Haskell.TH
 let v = mkName "T" in [| data $v …
Run Code Online (Sandbox Code Playgroud)

haskell template-haskell

7
推荐指数
1
解决办法
994
查看次数

打印并执行字符串

我发现自己写了很多代码

putStr "foo (bar 1) (bar 2) ="
print $ foo (bar 1) (bar 2)

麻烦的是,打印的消息可能与实际执行的代码不同步.显而易见的解决方案是自动生成此代码.

一种方法是将所有文本放在一个文件中,然后编写一个小程序来读取文件并从中生成Haskell源代码.但另一种选择是使用Template Haskell.

有没有人知道如何编写一个函数来获取String并从中生成上述代码?我猜它应该很容易,但TH没有很好的记录.

haskell template-haskell

7
推荐指数
1
解决办法
544
查看次数

获取其中的函数名称

我有一大堆的功能,如:method1,method2,method3.对于所有的人也有HUnit类似的测试功能:testMethod1,testMethod2,testMethod3.

testMethod1 = TestCase $
  assertEqual "testmethod1" ...

testMethod2 = TestCase $
  assertEqual "testmethod2" ...

testMethod3 = TestCase $
  assertEqual "testmethod3" ...
Run Code Online (Sandbox Code Playgroud)

我想避免将函数名称的冗余复制作为错误消息的前缀,并将其称为:

testMethod1 = TestCase $
  assertEqual_ ...
Run Code Online (Sandbox Code Playgroud)

如何实现(任何"魔术"技巧都被欣赏)?

所以实际上问题是如何在其定义中采用函数名称?


更新.

从原始问题实际上并不清楚,我也想处理这种情况:

tProcess = TestCase $ do
  assertEqual "tProcess" testResult $ someTest
  assertEqual "tProcess" anotherTestResult $ anotherTest
  assertEqual "tProcess" resultAgain $ testAgain
Run Code Online (Sandbox Code Playgroud)

最后我想写一些类似的东西:

tProcess = TestCase $ do
  assertEqual_ testResult $ someTest
  assertEqual_ anotherTestResult …
Run Code Online (Sandbox Code Playgroud)

haskell hunit template-haskell

7
推荐指数
1
解决办法
1296
查看次数

为什么TemplateHaskell导致GHC加载包?

我有一个简单的模板Haskell程序,它打印当前模块的名称(Main,here):

{-# LANGUAGE TemplateHaskell #-}
module Main
( main
) where

import Language.Haskell.TH
import Language.Haskell.TH.Syntax

modName ? String
modName = $(fmap loc_module qLocation »= ?mod ? return (LitE (StringL mod) ))

main ? IO ()
main = putStrLn modName
Run Code Online (Sandbox Code Playgroud)

当我编译它时,我从ghc获得以下加载消息:

tsuraan@localhost ~/test/modname $ ghc --make Main
[1 of 1] Compiling Main             ( Main.hs, Main.o )
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Loading package array-0.4.0.0 ... …
Run Code Online (Sandbox Code Playgroud)

haskell template-haskell

7
推荐指数
1
解决办法
261
查看次数

如何使用Template Haskell来获取函数体?

目前我正在尝试从Haskell子集进行转换,而不必处理所有解析,类型检查等问题.文档没有帮助我找出一个函数来获取函数的主体(所有定义)的名称.

此调用的上下文应该类似于

fac 0 = 1
fac x = z * fac (x - 1)

getBody = ...

main = do
    x <- runQ $ getBody [| fac |]
    print x
Run Code Online (Sandbox Code Playgroud)

有谁知道

  1. 是否有关于TH的一些好的和最新的文档(不是关于Hackage的参考)或
  2. 如何制作getBody?

haskell template-haskell

7
推荐指数
1
解决办法
358
查看次数

模板Haskell:GHC阶段限制以及如何克服

我在模块中有以下代码:

{-# LANGUAGE TemplateHaskell #-}

module Alpha where

import Language.Haskell.TH
import Data.List

data Alpha = Alpha { name :: String, value :: Int } deriving (Show)
findName n = find ((== n) . name)

findx obj = sequence [valD pat bod []]
    where
        nam = name obj
        pat = varP (mkName $ "find" ++ nam)
        bod = normalB [| findName nam |]
Run Code Online (Sandbox Code Playgroud)

然后我在主文件中有以下内容:

{-# LANGUAGE TemplateHaskell #-}

import Alpha

one   = Alpha "One" 1
two   = Alpha "Two" 2
three …
Run Code Online (Sandbox Code Playgroud)

haskell template-haskell

7
推荐指数
1
解决办法
1254
查看次数

带有模板haskell的多个函数定义

假设我有这样的数据类型:

data Color = Red | Blue | Green
Run Code Online (Sandbox Code Playgroud)

如何使用templatehaskell生成这样的函数?

myShow Red   = ...
myShow Blue  = ...
myShow Green = ...
Run Code Online (Sandbox Code Playgroud)

即我正在寻找基于模式匹配的函数的多个定义.

haskell template-haskell

7
推荐指数
1
解决办法
99
查看次数

在Template Haskell splice中规范化类型族实例

我正在使用该genifunctors包为其定义涉及类型族的类型生成仿函数实例.

第一个模块定义数据类型本身:

{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE KindSignatures #-}
{-# LANGUAGE DataKinds #-}
module Temp where

data Record (p :: (*,*))

type family Fst p where Fst (Record '(a,b)) = a
type family Snd p where Snd (Record '(a,b)) = b

data Bar s = Bar {
  field_a :: Fst s,
  field_b :: Snd s
}

newtype Baz a = Baz { getBaz :: Bar (Record '(Maybe a, [a])) }
Run Code Online (Sandbox Code Playgroud)

这与预期一样:

?> import Temp 
?> :t Baz …
Run Code Online (Sandbox Code Playgroud)

haskell ghc type-families template-haskell data-kinds

7
推荐指数
0
解决办法
187
查看次数

如何在 Haskell 中将类型信息带入值级别?

我正在寻找将类型信息带入 Haskell 中的值级别的方法。

我知道将任何类型信息表示为值的一种方法是Language.Haskell.TH.Type. 有什么方法可以实现接受Proxy a并返回Language.Haskell.TH.Type类型(或表示任何类型的替代类型)的函数a,如下所示?

如果您有更好的想法将类型信息作为不使用的值Language.Haskell.TH.Type,也请告诉我。

import Data.Proxy (Proxy)
import Language.Haskell.TH (Type, TypeQ)

-- |
-- >>> amazing (Proxy :: Proxy Bool)
-- ConT GHC.Types.Bool
--
-- >>> amazing (Proxy :: Proxy [String])
-- AppT ListT (ConT GHC.Base.String)
amazing :: Proxy a -> Type
amazing p = undefined

-- |
-- Or if above is impossible, how about this?
amazingQ :: Proxy a -> TypeQ
amazingQ p = undefined
Run Code Online (Sandbox Code Playgroud)

haskell template-haskell type-level-computation

7
推荐指数
1
解决办法
587
查看次数

如何使用 Template Haskell 构建多态结构?

我可以写一个实例

-- In Data.Sequence.Internal
instance Lift a => Lift (Seq a) where
  ...
Run Code Online (Sandbox Code Playgroud)

让用户将完全实现的序列提升到拼接中。但是假设我想要一些不同的东西,来构建用于创建序列的函数?

sequenceCode :: Quote m => Seq (Code m a) -> Code m (Seq a)
sequenceCode = ???
Run Code Online (Sandbox Code Playgroud)

我的想法是我能够写出类似的东西

triple :: a -> a -> a -> Seq a
triple a b c = $$(sequenceCode (fromList [[|| a ||], [|| b ||], [|| c ||]]))
Run Code Online (Sandbox Code Playgroud)

并让该函数直接使用底层序列构造函数构建其序列,而不必在运行时构建和转换列表。

使用它们的内部结构直接为序列编写类似的东西并不难sequenceCode(看下面的跳转)。但是,顾名思义,sequenceCode看起来很像sequence。有没有办法概括它?稍加思考就会发现这Traversable还不够。是否可以对分阶段泛型Generic1中的类做一些事情?我做了一些尝试,但我不太了解该包,不知道从哪里开始。即使只使用普通的旧 GHC 泛型也可能吗?我开始怀疑是这样,但我还没有尝试过,它肯定会很毛茸茸的。


这是一个版本的代码Data.Sequence

{-# language TemplateHaskellQuotes #-} …
Run Code Online (Sandbox Code Playgroud)

generics haskell template-haskell

7
推荐指数
1
解决办法
170
查看次数