从 Snap 访问 MongoDB
我正在尝试在拼接中使用 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 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
这是用类型签名注释的函数。我认为这可以做到
非常清楚问题出在哪里。
“liftIO $ do”块内的所有内容都必须是 IO 操作。最后一行
“休息结果”不是。一种解决方案是在该行前面添加“访问管道”
掌握“db”,就像您对 find 所做的那样。另一种解决方案是避免
调用“access pipeline...”两次,并将 find 行替换为以下内容:
然后将“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.
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:
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.
我不是 MongoDB 专家,所以我不是 100% 确定(而且我无法测试它),但我怀疑您的
liftIO
放在了错误的位置。我们有 liftIO :: MonadIO m => IO一-> m a,所以我们应该将liftIO
应用于实际上是IO
的操作,但我们希望它比IO
更大。我怀疑access
是一个返回类型大于IO
的函数。假设runIOE
、close
和rest
实际上都有IO
返回类型,然后我们会执行类似以下操作:如果其中一些操作实际上不是
IO
,那么您可以从这些操作中删除liftIO
。正如您所观察到的,这可以稍微清理一下:以
liftIO
开头的任何相邻行都可以合并。因此,如果上面的结果是liftIO
的正确位置,那么它也可以写为:(最后一个是可以的,因为
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 haveliftIO :: MonadIO m => IO a -> m a
, so we should applyliftIO
to actions that are actuallyIO
, but which we want to be something bigger thanIO
. I suspect thataccess
is a function with a bigger-than-IO
return type. AssumingrunIOE
,close
, andrest
all actually haveIO
return types, we'd then do something like this:If some of those actions actually are not
IO
things, then you can drop theliftIO
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 forliftIO
s, then it could also be written as:(The last one there is OK because
return = liftIO . return
for any sane implementation ofliftIO
.)