可以使用模板Haskell生成哈姆雷特代码吗?

Can I Use Template Haskell to Generate Hamlet Code?

我遇到了一个有趣的问题,我认为它可能是模板 Haskell 的相关位置。我正在使用 yesod 和 yesod-persistant 开发数据库的 Web 前端。我正在使用 mkPerist 函数和 persistLowerCase 准引号生成我的数据库类型。 我的问题是,我需要一种方法来编辑数据库的字段,但是为每个列的六个不同页面编写小村庄代码似乎重复得难以置信。我想我可以使用模板 Haskell 来自动生成文本字段和复选框,以便在给定类型的情况下编辑数据库的该列。理想情况下,我只是将类型的名称传递给模板 Haskell 函数,然后 TH 会负责为页面生成所有 Hamlet。我的问题是,在这种情况下我可以使用模板 Haskell 吗?这是最好的解决方案吗?特别是,Template Haskell 可以为其他准引用生成代码吗?特别是哈姆雷特?这是我目前的项目 link:https://github.com/ProspectRidgeTech/PRADatabase 提前致谢! (PS。让我知道是否有更好的方法来解决这个问题,如果您对我的问题有任何建议的修改。)

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

[hamlet|blah blah|]

您可以将其替换为(或等价物)

$(hamlet "blah blah")

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

无论如何,如果您的问题是为持久实体生成 table,我认为您根本不需要 TH,只需使用持久字段信息即可。我遇到了类似的问题并编写了一些代码,这些代码为实体列表生成 Html table。修改输入法应该不难吧。

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}
|]

编写处理表单和更新数据库的代码可能更棘手,需要 TH,但是这一步没有 Hamlet。