3

splice で mongodb haskell ドライバーを使用して mongo にアクセスしようとしています (スナップ ドライバーはスナップ > 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]

mongo アクションは IO モナド内で発生するため、そこで liftIO を使用する必要があることを理解しており、それを引き出したいと考えています。私の理解が崩壊するのは、そのスプライスをコンパイルした結果です。

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

「コードを送ってください」という質問を投稿して申し訳ありませんが、途方に暮れています。どこが間違っているのか、どうすればこれを機能させることができますか?

4

2 に答える 2

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 アクションでなければなりません。最後の行の「残りの結果」はそうではありません。解決策の 1 つは、find で行ったのと同じように、その行の先頭に「access pipe master "db"」を追加することです。もう 1 つの解決策は、"access pipe..." を 2 回呼び出すのを避け、検索行を次のように置き換えることです。

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

次に、「rest result」行を「return result」に置き換えます

LiftIO を必要としない検索行について Daniel が言っていることは正しいのですが、この場合は IO に MonadIO インスタンスがあるため問題ではありません。したがって、liftIO のすべてのものを 1 つのブロックに保持するのはおそらく同じくらい簡単です。

于 2011-11-21T02:35:31.647 に答える
2

私は MongoDB の専門家ではないので、100% 確信があるわけではありません (また、テストすることもできません) liftIO。を持っているので、実際には であるアクションにliftIO :: MonadIO m => IO a -> m a適用する必要がありますが、それよりも大きなものになりたいと考えています。戻り値より大きい型の関数だと思います。、、およびすべてが実際に戻り値の型を持っていると仮定すると、次のようになります。liftIOIOIOaccessIOrunIOEcloserestIO

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合体できます。したがって、上記が s の適切な場所であることが判明した場合、次のよう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]

(最後のものはOKです。なぜならreturn = liftIO . return、の正常な実装のためですliftIO。)

于 2011-11-19T19:52:27.240 に答える