Reputation: 9519
I've got a yesod handler that can accept some json with an array of objects. I'd like to insert all the objects into the database.
newtype NodeList = NodeList [Node]
instance FromJSON NodeList where
parseJSON (Object o) = NodeList <$> o .: "nodes"
parseJSON _ = mzero
postMoreNodesR :: Handler ()
postMoreNodesR = do
nodes::NodeList <- requireJsonBody
runDB $ mapM_ insert nodes
return ()
But some how, its not recognizing my entity type. (although other POST and GET handlers in the same module work great.) I can tell I'm pretty close, but I'm not sure what to do, since "a0" is not a type I've declared anywhere. Here's the error:
Handler/Node.hs:46:30:
Couldn't match expected type `[a0]' with actual type `NodeList'
In the second argument of `mapM_', namely `nodes'
In the second argument of `($)', namely `mapM_ insert nodes'
In a stmt of a 'do' block: runDB $ mapM_ insert nodes
Upvotes: 2
Views: 286
Reputation: 151
You can also pattern match directly in the bind:
postMoreNodesR :: Handler ()
postMoreNodesR = do
NodeList nodes <- requireJsonBody
runDB $ mapM_ insert nodes
return ()
This obviates the need for the type annotation as well.
It works because the do expression is de-sugared to a lambda:
requireJsonBody >>= \NodeList nodes -> runDB -- ...
Upvotes: 3
Reputation: 9519
I figured it out! I followed the types and realized I needed a helper function to extract the Nodes from the newtyped NodeList:
getNodesFromList :: NodeList -> [Node]
getNodesFromList (NodeList l) = l
Then my handler function became:
postMoreNodesR :: Handler ()
postMoreNodesR = do
nodes::NodeList <- requireJsonBody
runDB $ mapM_ insert $ getNodesFromList nodes
return ()
This stuff is really starting to click!
Upvotes: 1