Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/8.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在TemplateHaskell中使用列表_Haskell_Template Haskell - Fatal编程技术网

在TemplateHaskell中使用列表

在TemplateHaskell中使用列表,haskell,template-haskell,Haskell,Template Haskell,他有一个例子,tupleReplicate,它返回一个函数,该函数接受一个值并复制它: tupleReplicate :: Int -> Q Exp tupleReplicate n = do id <- newName "x" return $ LamE (VarP id) (TupE $ replicate n $ VarE id) 但这不起作用,因为ListE返

他有一个例子,
tupleReplicate
,它返回一个函数,该函数接受一个值并复制它:

tupleReplicate :: Int -> Q Exp
tupleReplicate n = do id <- newName "x"
                      return $ LamE (VarP id)
                                    (TupE $ replicate n $ VarE id)
但这不起作用,因为
ListE
返回
Exp
,而不是
[Exp]

更一般地说,我想在TemplateHaskell中编写一个接受列表并对其应用函数的函数


这里有一些示例代码,我正在尝试编写一个函数,如

makeModel (id_ : name_ : []) = Person (fromSql id_) (fromSql name_)

首先,让我们打开一些扩展:

{-# LANGUAGE FlexibleInstances, TemplateHaskell #-}

import Language.Haskell.TH
现在,我将伪造一些数据类型和类,以保持与现实世界的低交互:

data Person = Person Int String deriving Show

class SQL a where 
  fromSql :: String -> a

instance SQL Int where fromSql = read
instance SQL String where fromSql = id -- This is why I needed FlexibleInstances
好的,现在我们需要决定要生成什么代码。根据您的示例,我们可以将makeModel定义为lambda表达式(下面的翻译):

(我不会说流利的
Exp
,我在ghci中运行了
runQ[|\[id,name]->Person(fromSql id)(fromSql name)|]

我选择使用字符串来定义标识符
id
name
,因为您可以从表中读取,但也可以生成名为
field\u 1
的标识符

makeMakeModel qFieldNames qMapFunction qConstructor =  -- ["id","name"] 'fromSql 'Person
      LamE [ListP (map VarP qFieldNames)]              -- \ [id,name]
           $ foldl AppE (ConE qConstructor)            -- Person  
                        [AppE (VarE qMapFunction) (VarE name)|name <- qFieldNames]
                                                       -- $ id $ name

makeModel fieldNames mapFunction constructor = do
   names <- mapM newName fieldNames
   return $ makeMakeModel names mapFunction constructor
请注意,我们用
newName
创建的标识符是如何获得序列号以使其唯一的,而我们在前面用破折号传递的那些标识符,
'fromSql
'Person
保留为它们的实际定义


如果不想使用lambda表达式,可以使用

runQ [d| makeModel [id,name] = Person (fromSql id) (fromSql name) |]

作为起点-
[d |…|]
用于函数定义。

您希望生成的函数看起来像什么?
tuplerplicate 3
扩展为
\x->(x,x,x)
。对于列表,您希望TH扩展到什么?我正在将数据库行转换为对象。所以我得到一个数据库行作为列表:
[SqlValue]
。现在我想把它转换成一个对象
MyObject
接受6个值,我的列表中有6项。所以我想在TemplateHaskell中编写一个函数,给定这个列表,它将返回
MyObject
@n.m.的一个实例:请看这里:哦,我想我找到了。您是否正在尝试生成类似于
的代码,其中makeModel[id,name]=Person(fromSql id)(fromSql name)
?另请参见另一个示例。谢谢您!这很有帮助。
makeMakeModel qFieldNames qMapFunction qConstructor =  -- ["id","name"] 'fromSql 'Person
      LamE [ListP (map VarP qFieldNames)]              -- \ [id,name]
           $ foldl AppE (ConE qConstructor)            -- Person  
                        [AppE (VarE qMapFunction) (VarE name)|name <- qFieldNames]
                                                       -- $ id $ name

makeModel fieldNames mapFunction constructor = do
   names <- mapM newName fieldNames
   return $ makeMakeModel names mapFunction constructor
*Main> runQ $ makeModel ["id","name"] 'fromSql 'Person
LamE [ListP [VarP id_0,VarP name_1]] (AppE (AppE (ConE Main.Person) (AppE (VarE Main.fromSql) (VarE id_0))) (AppE (VarE Main.fromSql) (VarE name_1)))

*Main> $(makeModel ["id","name"] 'fromSql 'Person) ["1234","James"]
Person 1234 "James"
runQ [d| makeModel [id,name] = Person (fromSql id) (fromSql name) |]