2

我有一个 yesod 处理程序,它可以接受一些带有对象数组的 json。我想将所有对象插入数据库。

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 ()

但是有些方法,它无法识别我的实体类型。(尽管同一模块中的其他 POST 和 GET 处理程序工作得很好。)我可以说我已经很接近了,但我不确定该怎么做,因为“a0”不是我在任何地方声明的类型。这是错误:

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
4

2 回答 2

3

您还可以直接在绑定中进行模式匹配:

postMoreNodesR :: Handler ()
postMoreNodesR = do
  NodeList nodes <- requireJsonBody

  runDB $ mapM_ insert nodes

  return ()

这也消除了对类型注释的需要。

它之所以有效,是因为 do 表达式已被脱糖为 lambda:

requireJsonBody >>= \NodeList nodes -> runDB -- ...
于 2014-07-11T01:56:56.190 回答
1

我想到了!我遵循了类型并意识到我需要一个辅助函数来从新类型的 NodeList 中提取节点:

getNodesFromList :: NodeList -> [Node]
getNodesFromList (NodeList l) = l

然后我的处理函数变成了:

postMoreNodesR :: Handler ()
postMoreNodesR = do
        nodes::NodeList <- requireJsonBody
        runDB $ mapM_ insert $ getNodesFromList nodes
        return ()

这东西真的开始点击了!

于 2014-07-11T01:06:58.477 回答