2016-11-26 40 views
1

我遇到了一個有趣的問題,我認爲這可能是模板哈斯克爾的一個相關地方。我正在使用yesod和yesod-persistant在Web數據庫的前端工作。我使用mkPerist函數和persistLowerCase準報價生成我的數據庫類型。 我的問題是,我需要一種方法來編輯數據庫的字段,但編寫六個不同頁面的每個列的哈姆雷特代碼似乎令人難以置信的重複。我想我可以使用模板Haskell自動生成文本字段和複選框,以便根據類型編輯該數據庫的列。理想情況下,我只需將該類型的名稱傳遞給模板Haskell函數,然後TH將負責爲頁面生成所有的哈姆雷特。我的問題是,我可以在這種情況下使用模板哈斯克爾?這是最好的解決方案嗎?特別是,模板Haskell可以爲其他準標準器生成代碼嗎?特別是哈姆雷特?這裏是我的項目截至目前的鏈接:https://github.com/ProspectRidgeTech/PRADatabase在此先感謝! (PS。讓我知道是否有更好的方法來解決這個問題,如果你有任何建議編輯我的問題。)我可以使用模板Haskell生成哈姆雷特代碼嗎?

回答

1

回答你的問題:是的,你可以,但我不會推薦它。準加引號只是其中一個字符串並將產生一些代碼的函數,因此,當你看到

[hamlet|blah blah|] 

你可以將其替換爲(或同等學歷)

$(hamlet "blah blah") 

所以沒有什麼可以阻止你TH生成一個字符串給它的一個調用哈姆雷特。然而,TH的一個要點是類型安全。 生成一個字符串,然後解析它的對象類型。而且,這兩步代碼生成可能很難調試。

無論如何,如果你的問題是爲持久實體生成表,我不認爲你需要TH,只是使用Persistent字段信息。我有一個類似的問題,並編寫了一些代碼,爲實體列表生成一個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,但沒有包括在該步驟哈姆雷特。

+0

謝謝!我認爲,如果我能解決這個問題的至少一部分而沒有TH,那絕對是解決問題的方法!我不知道持續提供這種類型的信息!作爲一個快速跟進問題,參數'getColumn'從哪裏來?我假設我可以做一些像'(runDB $ selectList [] [])''來獲得列表中所有'實體'的列表,但是'(FieldDef - > Text)'做了什麼?另外,你可以將我鏈接到定義這些持久函數的模塊嗎?感謝您的幫助! – thelostlambda

+0

'getColumn :: FieldDef - > Text'只是一個從列定義中提取名稱以將其用於列名稱的函數。我個人使用'unDBName。 fieldDB「,但您可以更改以更改大小寫。 – mb14

+0

[there](https://hackage.haskell.org/package/persistent-2.6/docs/Database-Persist-Types.html) – mb14

相關問題