我正在阅读pozorvlak在Template Haskell上发布的婴儿步骤帖子,试图自己理解它,我发现了这一部分:
回想一下,我们试图以编程方式生成表单的声明
data Fred = Fred.让我们用quasiquoting来试试吧.由于调用TH代码的限制,我们必须将它放在自己的模块中,所以让我们将以下内容放在Keyword.h中,以便编译器可以找到它:Run Code Online (Sandbox Code Playgroud)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 `$('
这跟我打了个响铃,看起来和我最近读到的其他东西一样,模板Haskell包文档:
对于动态绑定的thing(
NameS),我们可能希望它们以依赖于上下文的方式,因此我们再次不需要名称空间.例如:Run Code Online (Sandbox Code Playgroud)let v = mkName "T" in [| data $v = $v |]这里我们
Name对类型构造函数和数据构造函数使用相同的
嗯,这几乎是一样的,让我们看看我能不能这样做:
module Example where
import Language.Haskell.TH
let v = mkName "T" in [| data $v …Run Code Online (Sandbox Code Playgroud) 我发现自己写了很多代码
putStr "foo (bar 1) (bar 2) =" print $ foo (bar 1) (bar 2)
麻烦的是,打印的消息可能与实际执行的代码不同步.显而易见的解决方案是自动生成此代码.
一种方法是将所有文本放在一个文件中,然后编写一个小程序来读取文件并从中生成Haskell源代码.但另一种选择是使用Template Haskell.
有没有人知道如何编写一个函数来获取String并从中生成上述代码?我猜它应该很容易,但TH没有很好的记录.
我有一大堆的功能,如: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程序,它打印当前模块的名称(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子集进行转换,而不必处理所有解析,类型检查等问题.文档没有帮助我找出一个函数来获取函数的主体(所有定义)的名称.
此调用的上下文应该类似于
fac 0 = 1
fac x = z * fac (x - 1)
getBody = ...
main = do
x <- runQ $ getBody [| fac |]
print x
Run Code Online (Sandbox Code Playgroud)
有谁知道
我在模块中有以下代码:
{-# 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) 假设我有这样的数据类型:
data Color = Red | Blue | Green
Run Code Online (Sandbox Code Playgroud)
如何使用templatehaskell生成这样的函数?
myShow Red = ...
myShow Blue = ...
myShow Green = ...
Run Code Online (Sandbox Code Playgroud)
即我正在寻找基于模式匹配的函数的多个定义.
我正在使用该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 中的值级别的方法。
我知道将任何类型信息表示为值的一种方法是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) 我可以写一个实例
-- 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)