Database 我可以使用模板Haskell生成Hamlet代码吗?

Database 我可以使用模板Haskell生成Hamlet代码吗?,database,haskell,yesod,template-haskell,hamlet,Database,Haskell,Yesod,Template Haskell,Hamlet,我遇到了一个有趣的问题,我认为它可能是模板Haskell的合适位置。我正在使用YesSOD和YesSOD persistant开发数据库的web前端。我使用mkPerist函数和persistLowerCase准引号生成数据库类型。 我的问题是,我需要一种编辑数据库字段的方法,但是为每一列的六个不同页面编写hamlet代码似乎是极其重复的。我想我可以使用TemplateHaskell自动生成文本字段和复选框,用于编辑给定类型的数据库列。理想情况下,我只需将类型的名称传递给模板Haskell函数,

我遇到了一个有趣的问题,我认为它可能是模板Haskell的合适位置。我正在使用YesSOD和YesSOD persistant开发数据库的web前端。我使用
mkPerist
函数和
persistLowerCase
准引号生成数据库类型。
我的问题是,我需要一种编辑数据库字段的方法,但是为每一列的六个不同页面编写hamlet代码似乎是极其重复的。我想我可以使用TemplateHaskell自动生成文本字段和复选框,用于编辑给定类型的数据库列。理想情况下,我只需将类型的名称传递给模板Haskell函数,然后TH将负责为页面生成所有的Hamlet。我的问题是,在这种情况下我可以使用模板Haskell吗?这是最好的解决方案吗?特别是,模板Haskell是否可以为其他准引号生成代码?特别是哈姆雷特?这里有一个链接到我现在的项目:提前感谢!(注:请告诉我是否有更好的方法解决此问题,以及您是否建议对我的问题进行编辑。)

回答您的问题:可以,但我不推荐。准引号只是一个函数,它接受一个字符串并生成一些代码,所以当您看到

[hamlet|blah blah|]
您可以将其替换为(或等效)

所以,没有什么能阻止你生成一个字符串,并调用哈姆雷特。然而,其中一点是类型安全。 生成一个字符串,然后解析它的对象。此外,这两步代码生成可能很难调试

无论如何,若您的问题是为持久性实体生成表,我认为您根本不需要它,只需要使用持久性字段信息。我遇到了一个类似的问题,编写了一些代码,为实体列表生成一个Html表。通过输入修改它应该不难

entitiesToTable :: PersistEntity a => (FieldDef -> Text) -> [Entity a] -> Html
entitiesToTable getColumn entities = do
  let eDef = entityDef (map entityVal entities)
  [shamlet|
<table.table.table-bordered.table-striped class="#{unHaskellName $ entityHaskell eDef}">
  <tr>
    <th> Id
    $forall field <- entityFields eDef
      <th> #{getColumn field}
  $forall Entity eit entity  <- entities
    <tr>
      <td.id> #{renderPersistValue $ toPersistValue eit}
      $forall (pfield, fieldDef) <- zip (toPersistFields entity) (entityFields eDef)
        <td class="#{getHaskellName fieldDef}" > #{renderPersistValue $ toPersistValue pfield}
|]
EntityToTable::PersistEntity a=>(FieldDef->Text)->[Entity a]->Html
entitiesToTable getColumn entities=do
设eDef=entityDef(映射entityVal实体)
[香叶|
身份证件

$forall field谢谢!我想如果我能在不使用TH的情况下至少解决部分问题,那绝对是解决问题的方法!我不知道Persistent提供了这种类型的信息!作为一个快速跟进问题,参数
getColumn
来自哪里?我想我可以做类似
(runDB$selectList[][])
从某一列获取所有
实体的I列表,但是
(FieldDef->Text)的作用是什么
do?另外,您能将我链接到定义这些持久性函数的模块吗?谢谢您的帮助!
getColumn::FieldDef->Text
只是一个从列定义中提取名称以用于列名的函数。我个人使用
unDBName.fieldDB
,但您可以更改为例如,他就是一个例子。太棒了!谢谢你的迅速回复!我想这就是我所需要的!再次感谢!
entitiesToTable :: PersistEntity a => (FieldDef -> Text) -> [Entity a] -> Html
entitiesToTable getColumn entities = do
  let eDef = entityDef (map entityVal entities)
  [shamlet|
<table.table.table-bordered.table-striped class="#{unHaskellName $ entityHaskell eDef}">
  <tr>
    <th> Id
    $forall field <- entityFields eDef
      <th> #{getColumn field}
  $forall Entity eit entity  <- entities
    <tr>
      <td.id> #{renderPersistValue $ toPersistValue eit}
      $forall (pfield, fieldDef) <- zip (toPersistFields entity) (entityFields eDef)
        <td class="#{getHaskellName fieldDef}" > #{renderPersistValue $ toPersistValue pfield}
|]