2011-11-19 96 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