从 Snap 访问 MongoDB

发布于 2024-12-16 23:35:26 字数 664 浏览 2 评论 0原文

我正在尝试在拼接中使用 mongodb haskell 驱动程序访问 mongo(snap 驱动程序似乎已损坏,因为 snap > 0.5)。

这是我到目前为止所得到的:

testSplice :: Splice AppHandler
testSplice = do
  record <- liftIO $ do
    pipe <- runIOE $ connect (host "127.0.0.1") 
    results <- access pipe master "db" (find $ select [] "coll")
    close pipe
    rest result

  return $ [TextNode $ T.pack $ show $ records]

我知道我需要在那里使用 liftIO,因为 mongo 操作发生在 IO monad 内部,我想将其撤回。我的理解崩溃的地方是编译该拼接的结果:

Couldn't match expected type `IO a0'
    with actual type `Action m0 [Database.MongoDB.Document]'

我很抱歉发布一个“请将代码发送给我”的问题,但我不知所措:我哪里出错了,我该如何做这个工作?

I'm trying to access mongo using the mongodb haskell drivers (the snap driver appears to be broken for snap > 0.5) in splice.

This is as far as I've got so far:

testSplice :: Splice AppHandler
testSplice = do
  record <- liftIO $ do
    pipe <- runIOE $ connect (host "127.0.0.1") 
    results <- access pipe master "db" (find $ select [] "coll")
    close pipe
    rest result

  return $ [TextNode $ T.pack $ show $ records]

I understand that I need to use liftIO there, as the mongo action occurs inside an IO monad, and I want to pull that back out. Where my understanding breaks down is the result of compiling that splice:

Couldn't match expected type `IO a0'
    with actual type `Action m0 [Database.MongoDB.Document]'

I'm sorry to post a "Send me the codes plz" question, but I'm at loss: where am I going wrong, and how do I make this work?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

云朵有点甜 2024-12-23 23:35:26

这是用类型签名注释的函数。我认为这可以做到
非常清楚问题出在哪里。

testSplice :: Splice AppHandler
testSplice = do
  record <- liftIO $ do
    pipe <- runIOE $ connect (host "127.0.0.1") -- :: IO Pipe
    results <- access pipe master "db" (find $ select [] "coll")
    -- ^ :: IO (Either Failure Cursor)
    close pipe -- :: IO ()
    rest result -- :: Action m [Document]

  return $ [TextNode $ T.pack $ show $ records]

“liftIO $ do”块内的所有内容都必须是 IO 操作。最后一行
“休息结果”不是。一种解决方案是在该行前面添加“访问管道”
掌握“db”,就像您对 find 所做的那样。另一种解决方案是避免
调用“access pipeline...”两次,并将 find 行替换为以下内容:

result <- access pipe master "db" (find (select [] "coll") >>= rest)

然后将“rest result”行替换为“return result”

丹尼尔关于不需要 liftIO 的 find 行的说法是正确的,但在
这种情况并不重要,因为 IO 有一个 MonadIO 实例。因此,将所有 liftIO 内容保存在一个块中可能同样容易。

Here is your function annotated with type signatures. I think this makes it
pretty clear where the problem lies.

testSplice :: Splice AppHandler
testSplice = do
  record <- liftIO $ do
    pipe <- runIOE $ connect (host "127.0.0.1") -- :: IO Pipe
    results <- access pipe master "db" (find $ select [] "coll")
    -- ^ :: IO (Either Failure Cursor)
    close pipe -- :: IO ()
    rest result -- :: Action m [Document]

  return $ [TextNode $ T.pack $ show $ records]

Everything inside the "liftIO $ do" block must be an IO action. The last line
"rest result" is not. One solution is to prepend that line with 'access pipe
master "db"' just like you've done with find. Another solution is to avoid
calling "access pipe..." twice and replace the find line with the following:

result <- access pipe master "db" (find (select [] "coll") >>= rest)

Then replace the "rest result" line with "return result"

What Daniel says about the find line not needing liftIO is correct, but in
this case it doesn't matter because IO has a MonadIO instance. So it's probably just as easy to keep all the liftIO stuff in one block.

一江春梦 2024-12-23 23:35:26

我不是 MongoDB 专家,所以我不是 100% 确定(而且我无法测试它),但我怀疑您的 liftIO 放在了错误的位置。我们有 liftIO :: MonadIO m => IO一-> m a,所以我们应该将 liftIO 应用于实际上是 IO 的操作,但我们希望它比 IO 更大。我怀疑 access 是一个返回类型大于 IO 的函数。假设 runIOEcloserest 实际上都有 IO 返回类型,然后我们会执行类似以下操作:

testSplice = do
    pipe <- liftIO . runIOE $ connect (host "127.0.0.1")
    results <- access pipe master "db" (find $ select [] "coll") -- note: no liftIO on this one because it's presumably already lifted
    liftIO $ close pipe
    record <- liftIO $ rest result
    return [TextNode . T.pack . show $ records]

如果其中一些操作实际上不是IO,那么您可以从这些操作中删除liftIO

正如您所观察到的,这可以稍微清理一下:以 liftIO 开头的任何相邻行都可以合并。因此,如果上面的结果是 liftIO 的正确位置,那么它也可以写为:(

testSplice = do
    pipe <- liftIO . runIOE $ connect (host "127.0.0.1")
    results <- access pipe master "db" (find $ select [] "coll")
    liftIO $ do
        close pipe
        record <- rest result
        return [TextNode . T.pack . show $ records]

最后一个是可以的,因为 return = liftIO .return对于 liftIO 的任何合理实现。)

I am not a MongoDB expert, so I'm not 100% sure (and I can't test it), but I suspect that you've got your liftIO in the wrong place. We have liftIO :: MonadIO m => IO a -> m a, so we should apply liftIO to actions that are actually IO, but which we want to be something bigger than IO. I suspect that access is a function with a bigger-than-IO return type. Assuming runIOE, close, and rest all actually have IO return types, we'd then do something like this:

testSplice = do
    pipe <- liftIO . runIOE $ connect (host "127.0.0.1")
    results <- access pipe master "db" (find $ select [] "coll") -- note: no liftIO on this one because it's presumably already lifted
    liftIO $ close pipe
    record <- liftIO $ rest result
    return [TextNode . T.pack . show $ records]

If some of those actions actually are not IO things, then you can drop the liftIO from those ones.

As you observed, this can be cleaned up a bit: any adjacent lines that start with liftIO can be coalesced. So if the above turns out to be the right places for liftIOs, then it could also be written as:

testSplice = do
    pipe <- liftIO . runIOE $ connect (host "127.0.0.1")
    results <- access pipe master "db" (find $ select [] "coll")
    liftIO $ do
        close pipe
        record <- rest result
        return [TextNode . T.pack . show $ records]

(The last one there is OK because return = liftIO . return for any sane implementation of liftIO.)

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文