如何让 yesod-persistent 识别我的 aeson 解析实体数组的类型?

Posted

技术标签:

【中文标题】如何让 yesod-persistent 识别我的 aeson 解析实体数组的类型?【英文标题】:how do I get yesod-persistent to recognize the type of my aeson parsed entity array? 【发布时间】:2014-07-11 00:32:35 【问题描述】:

我有一个 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

【问题讨论】:

【参考方案1】:

你也可以直接在绑定中进行模式匹配:

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

  runDB $ mapM_ insert nodes

  return ()

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

它之所以有效,是因为 do 表达式被取消了对 lambda 的糖分:

requireJsonBody >>= \NodeList nodes -> runDB -- ...

【讨论】:

更好!我不知道你可以在 do 块内进行模式匹配。 它实际上并没有脱糖为 lambda。它比这更复杂,感谢fail【参考方案2】:

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

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

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

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

这玩意儿真的开始点击了!

【讨论】:

实际上,Haskell 可以自动为您生成该函数:) data NodeList = NodeList getNodesFromList :: [Node]

以上是关于如何让 yesod-persistent 识别我的 aeson 解析实体数组的类型?的主要内容,如果未能解决你的问题,请参考以下文章

如何让动画和手势识别器协同工作? (迅速)

SWIFT4:如何让两个点击手势识别器一起工作

如何让phpThumb识别并使用ImageMagick安装?

如何让 Eclipse 识别来自 SBT 的依赖项

如何让这个alexa技能识别两个意图

如何让Gulp识别编译文件中的更改/更新?