在 map / forM 中使用 updateWhere

Posted

技术标签:

【中文标题】在 map / forM 中使用 updateWhere【英文标题】:Using updateWhere inside a map / forM 【发布时间】:2013-08-01 19:55:47 【问题描述】:

列表中的每个元素都会触发一些数据库更新,但我一直卡在返回类型上。你能告诉我这样做的正确方法是什么吗?

for ::  [a] -> (a -> b) -> [b]
for xs f = map f xs

-- Summary: Loop over the elements of xs and update the table for each element
-- get an ID from the element
-- get the record corresponding to that ID
-- extract more values
-- update table (below is just a dummy updateWhere 
-- but the above values will be used in the update eventually )
forM_ xs $ \(Entity xid val) -> do
            let qid = tableField val 
            y <- runDB $ get404 qid
            let z = table2Field y
            return $ updateWhere [PersonName ==. "Test"] [PersonAge *=. 1] 

我收到以下错误:

Couldn't match type `PersistMonadBackend m0'
               with `persistent-1.2.1:Database.Persist.Sql.Types.SqlBackend'
Expected type: PersistMonadBackend m0
  Actual type: PersistEntityBackend Person
In the second argument of `($)', namely
  `updateWhere [PersonName ==. name] [PersonAge *=. 1]'

我尝试使用 for 而不是 forM or forM_,但它没有解决任何问题。在这一点上,我只是在尝试一大堆组合,而没有真正理解如何解决这个错误。感谢你的帮助!

更新:

这是我正在使用的实际代码。当我摆脱大多数 let 语句并只运行 updateWhere 并进行微不足道的更新时,它仍然给我同样的错误。

getCalculateDeltaR :: personId -> Handler html
getCalculateDeltaR personId = do

    goods <- runDB $ selectList [GoodPerson ==. personId] [] 

    forM goods $ \(Entity gid good) -> do
                let aid = goodAsset good  
                asset <- runDB $ get404 aid
                let mktValue = assetMktValue asset
                return $ updateWhere [GoodPerson ==. personId, GoodAsset = aid] [GoodDelta =. (mktValue - GoodOrigValue)]  

    defaultLayout $ do
        $(widgetFile "calculateDelta")

如果我将上面的表单更改为:

    forM goods $ \(Entity gid good) -> do
                return $ updateWhere [GoodPerson ==. personId] [GoodDelta =. 1]  

我仍然收到关于不匹配类型的相同错误。

【问题讨论】:

去掉lambda最后一行的return是否有效? @bennofs 我是 Haskell 的新手,所以我不能说它是否“有效”,但没有返回它告诉我:“'do' 块中的最后一条语句必须是一个表达式”。我不知道这是否意味着只要我能返回一个正确的表达式,一切都会奏效。当我在 forM 之外使用 updateWhere 时,它​​工作正常。我的猜测与“做”有关,但我可能会离开这里。 你能显示更多代码吗,也许是你使用你发布的代码块的函数,包括它的类型签名? @bennofs 感谢您的帮助。我现在已经更新了我的帖子。代码在 Handler 中运行 【参考方案1】:

我对yesod不是很熟悉,但我认为下面的代码应该可以工作:

forM_ xs $ \(Entity xid val) -> do
        let qid = tableField val 
        y <- runDB $ get404 qid
        let z = table2Field y
        runDB $ updateWhere [PersonName ==. "Test"] [PersonAge *=. 1] 

您不想返回 DB 操作然后将它们丢弃(forM_ 丢弃单个返回值),因为这只会导致无操作。你必须运行它们。

【讨论】:

谢谢@bennofs。我觉得自己很愚蠢——盯着代码看了一会儿,但没有意识到我从来没有运行过这个动作。非常感谢您的帮助。

以上是关于在 map / forM 中使用 updateWhere的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 上的 Xamarin.Forms.Maps 中使用 Xamarin.Essentials Geolocation 获取设备位置的奇怪问题

如何在 Xamarin.Forms.Map 中获取当前位置或移动到当前位置

在运行时使用 Xamarin.Forms.Maps 创建折线时如何附加位置?

从 ViewModel 绑定到 Xamarin.Forms.Maps.Map

有没有办法动画Xamarin.Forms.Maps针运动

有没有办法在 iOS 项目上禁用 xamarin.forms.maps 上的信息窗口?