我有以下持久模型:
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/