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