2013-08-01 3 views
1

목록의 각 요소가 일부 DB 업데이트를 트리거하지만 반환 유형이 계속 변합니다. 이 작업을 수행하는 올바른 방법을 알려주십시오.map/forM 내부에서 updateWhere를 사용합니다.

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] 

나는 아직도 일치하지 않는 유형에 대해 같은 오류가 발생합니다.

+0

람다의 마지막 줄에서 반품을 제거하면 작동합니까? – bennofs

+0

@bennofs 저는 하스켈을 처음 사용하기 때문에 작동하지 않는다고 말할 수는 없지만 반환이 없다고 말하면서 : "do 블록의 마지막 문장은 표현식이어야합니다". 나는 내가 적절한 표현을 되 돌리는 한 그것이 작동한다는 것을 의미하는지 모른다. forM 외부에서 updateWhere를 사용하면 잘 작동합니다. 내 추측은 '할'과 관련이 있지만 여기서 벗어날 수 있습니다. – Ecognium

+0

더 많은 코드를 게시 할 수 있습니까? 예를 들어, 게시 한 코드 블록을 사용하는 유형의 시그니처를 포함하는 함수일까요? – bennofs

답변

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_ 개별 반환 값을 던졌습니다 어쨌든 그것은 아무런 조치도 취하지 않을 것이기 때문이다. 당신은 그들을 실행해야합니다.

+0

Thanks @bennofs. 나는 어리 석을 느낀다. 잠시 동안 코드를 쳐다 보았다.하지만 나는 결코 행동을 취하지 않았다는 것을 깨닫지 못했다. 도움을 주셔서 대단히 감사합니다. – Ecognium