2011-11-19 59 views
3

我试图在拼接中使用mongodb haskell驱动程序访问mongo(快照驱动程序在snap> 0.5时被破坏)。从捕捉访问MongoDB

这是据我已经走到这一步:

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那里,蒙戈行动的IO单子内发生,我想拉那句话出。当我的理解分解是在编译拼接的结果:

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

对不起张贴“送我的代码PLZ”的问题,但我在亏损:我要去错在何处,并我如何做这项工作?

回答

5

这里是你的函数注释类型签名。我认为这使得 相当清楚问题所在。

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操作。最后一行 “休息结果”不是。一种解决方法是用“访问管道 ”master“db”'来预先设置该行,就像您使用find所做的一样。另一种解决方案是避免 叫“接入管道的......”两次,并用以下替换行查找:

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

然后用“返回结果”

什么丹尼尔替换“休息结果”行说关于不需要liftIO的查找线是正确的,但在 这种情况下,它并不重要,因为IO有一个MonadIO实例。因此,将所有的升级工具放在一个区块中可能同样简单。

+0

谢谢,@mightybyte。我认为我忘了在“休息结果”之后加上'return'(它不会在这种状态下进行类型检查!)。 'find'('Action m Cursor')的结果与'rest'('Cursor - > Action m [Document]')之间的'bind'做到了这一点。 我在做什么错了,试图通过针对访问的值运行来将'rest'绑定到'Either Failure Cursor'。 再次感谢! – Khanzor

2

我不是一个MongoDB专家,所以我不是100%确定(我无法测试它),但我怀疑你的liftIO错误。我们有liftIO :: MonadIO m => IO a -> 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。)

+0

谢谢你的答案,丹尼尔:)。我明白你在说什么,但find的结果在IO中,所以我不认为这是问题。我撞着我的头是“rest”的结果,它是'Action m [Document]'。我只需要'[Document]'部分,我不明白我应该如何将它绑定到另一个monad中? – Khanzor