haskell - 如何在 Yesod/Persistent 中正确使用 runDB

标签 haskell yesod persistent

我有以下持久模型:

User
    ident Text
    password Text Maybe
     UniqueUser ident
    deriving Typeable

Payment
    timestamp UTCTime
    from UserId
    to UserId
    amount Int

我正在尝试构建一个页面,显示数据库中所有付款的列表,每个付款链接到支付/接收付款的用户。目前我的代码是:
getPaymentsR :: Handler Html
getPaymentsR = do
    let payments = map addFromTo $ runDB $ selectList [] [Desc PaymentTimestamp]
    defaultLayout
        [whamlet|
            <h3> Payments
            <ul>
                $forall (key, value, from, to) <- payments
                    <li>
                        <a href=@{UserR $ paymentFrom value}> #{from} </a> paid #{paymentAmount value} to <a href=@{UserR $ paymentTo value}> #{to} </a> on #{printDay $ paymentTimestamp value}
            $if null payments
                <ul>
                    <li> No payments
        |]
    where 
        addFromTo :: Entity Payment -> (Key Payment, Payment, Text, Text)
        addFromTo (Entity key val) = do
            let from = runDB $ get404 $ paymentFrom val
            let to = runDB $ get404 $ paymentTo val
            (key, val, userIdent from, userIdent to)

但是我收到以下错误:
Handler/Payment.hs:9:36:
    Couldn't match expected type `[Entity Payment]'
                with actual type `HandlerT site0 IO [Entity Payment]'
    In the second argument of `($)', namely
      `runDB $ selectList [] [Desc PaymentTimestamp]'
    In the expression:
      map addFromTo $ runDB $ selectList [] [Desc PaymentTimestamp]
    In an equation for `payments':
        payments
          = map addFromTo $ runDB $ selectList [] [Desc PaymentTimestamp]

Handler/Payment.hs:26:34:
    Couldn't match expected type `User'
                with actual type `HandlerT site0 IO User'
    In the first argument of `userIdent', namely `from'
    In the expression: userIdent from
    In a stmt of a 'do' block: (key, val, userIdent from, userIdent to)

Handler/Payment.hs:26:50:
    Couldn't match expected type `User'
                with actual type `HandlerT site1 IO User'
    In the first argument of `userIdent', namely `to'
    In the expression: userIdent to
    In a stmt of a 'do' block: (key, val, userIdent from, userIdent to)

有谁知道我做错了什么,或者如何解决这些错误?
我相信这与Extracting database field values inside a Handler有很大关系.
但是我仍然无法解决上面链接中的信息的问题。

更新

使用 Michael Snoyman 的答案编辑我的代码后,我的新 addFromTo 函数仍然给出类型错误:
addFromTo :: Entity Payment -> (Key Payment, Payment, Text, Text)
addFromTo (Entity key val) = do
    from' <- runDB $ get404 $ paymentFrom val
    to' <- runDB $ get404 $ paymentTo val
    let from = userIdent from'
    let to = userIdent to'
    (key, val, from, to)

最佳答案

这里的问题是您将 monadic 操作视为纯值。解决此问题的更简单方法是使用 do-notation 和 slurp 运算符:

payments' <- runDB $ selectList [] [Desc PaymentTimestamp]
let payments = map addFromTo payments'

或者,如果你想变得更高级(不一定推荐):
payments <- fmap (map addFromTo) $ runDB $ selectList [] [Desc PaymentTimestamp]

关于haskell - 如何在 Yesod/Persistent 中正确使用 runDB,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/20890971/

相关文章:

haskell - 如何在 Yesod 的组合 javascript 文件中对 Julius 文件进行排序?

css - 如何在 Yesod 中使用 CSS 框架?

haskell - 带有 Database.Persist 的 SQL 索引(Yesod web 框架)

r - data.table 的用户指定属性被删除

javascript - 在 Yii2 高级模板中制作持久化的 CSS 和 JS

list - 比较haskell中的字符串内容

haskell - 帮助我理解我的 Haskell ghci 配置文件中的函数

list - haskell 递归

haskell - 将 AJAX 与 warp HTTP 服务器结合使用

perl - 有状态的尾部(只显示上次执行的新行)