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

时间:2016-11-26 21:40:38

标签: database haskell yesod template-haskell hamlet

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

1 个答案:

答案 0 :(得分:1)

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

[hamlet|blah blah|]

您可以将其替换为(或等效的)

$(hamlet "blah blah")

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

无论如何,如果您的问题是为Persistent实体生成表格,我根本不认为您需要TH并只使用持久字段信息。我有一个类似的问题,写了一些代码,为实体列表生成一个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}
|]

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