簡體   English   中英

使用模板Haskell自動聲明yesod處理程序

[英]Automatically declaration yesod handlers using Template Haskell

例如,我在模型中有下一個實體類型

User json
    username Text

以及以下Haskell類型:

Entity User

刪除用戶的處理程序:

路線文件:

/users/#UserId UserR DELETE

處理程序聲明:

deleteUserR :: UserId -> Handler Value
deleteUserR uid = do
    runDB $ delete uid
    sendResponseStatus status200 ("DELETED" :: Text)

我想寫這樣的模板函數:

mkDeleteHandler :: String -> Q [Dec]
mkDeleteHandler name = do
    [d|hname idname = do
        runDB $ delete idname
        sendResponseStatus status200 ("DELETED" :: Text)|]
        where hname  = mkName ("delete" ++ name ++ "R")
              idname = mkName ("i" ++ name)

在我的Handler.User模塊中

mkDeleteHandler "User"

但這是行不通的。 編譯器寫下一條警告:

警告:已定義但未使用:hname

警告:已定義但未使用:idname

錯誤:

不在范圍內:deleteUserR

編輯:添加了簡單類型簽名參數化示例

我認為mkDeleteHandler函數名稱綁定存在問題。 我會嘗試例如以下示例(簡化示例):

mkHandler :: String -> String -> Q [Dec]
mkHandler typeName funcName = do
  funDecl <- [d| funcName :: String -> IO()
                 funcName var1 = do
                 print var1 |]

  let [SigD _ (AppT _ t0), FunD _ funBody] = funDecl
      sigBody' = (AppT (AppT ArrowT (ConT tname)) t0)

  return $ [SigD hname sigBody', FunD hname funBody]

  where
    hname  = mkName funcName
    tname = mkName typeName

然后,您可以像這樣拼接它:

data Foo = Foo Int
     deriving Show

$(mkHandler "Int" "handlerInt")
$(mkHandler "String" "handlerString")
$(mkHandler "Foo" "handlerFoo")

main = do
  handlerInt 5
  handlerString "Hello World"
  handlerFoo $ Foo 5

請注意, mkHandler應該在單獨的模塊中定義,並在使用前先導入。

您的問題是, hname沒有使用過hname ,就像編譯器已正確警告過一樣。 解決方法是,我們使用引號將其生成“模板”函數聲明,然后將生成的函數名稱替換為我們自己的hname

恕我直言,學習Template Haskell的最佳教程就是這一本

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM