简体   繁体   English

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

[英]How to use runDB correctly in Yesod / Persistent

I have the following persistent model: 我有以下持久模型:

User
    ident Text
    password Text Maybe
     UniqueUser ident
    deriving Typeable

Payment
    timestamp UTCTime
    from UserId
    to UserId
    amount Int

I am trying to build a page that displays a list of all payments in the database, with for each payment links to the users that paid / received the payment. 我正在尝试构建一个页面,显示数据库中所有付款的列表,每个付款链接指向付款/收到付款的用户。 Currently my code for this is: 目前我的代码是:

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)

However I am getting the following errors: 但是我收到以下错误:

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)

Does anybody know what I am doing wrong, or how to solve these errors? 有人知道我做错了什么,或者如何解决这些错误? I believe it has a lot to do with Extracting database field values inside a Handler . 我相信它与在Handler中提取数据库字段值有很大关系。 However I was still unable to resolve the problem with the information in above link. 但是我仍然无法解决上述链接中的信息问题。

Update 更新

After editing my code using Michael Snoyman's answer, my new addFromTo function is still giving type errors: 在使用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)

The issue here is that you're treating a monadic action as a pure value. 这里的问题是你将monadic动作视为纯粹的价值。 The easier way to resolve this is to use do-notation and the slurp operator: 解决这个问题的更简单方法是使用do-notation和slurp运算符:

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

Or if you want to get fancier (not necessarily recommended): 或者如果你想获得更好的(不一定推荐):

payments <- fmap (map addFromTo) $ runDB $ selectList [] [Desc PaymentTimestamp]

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM