Доступ к MongoDB из Snap - PullRequest
       25

Доступ к MongoDB из Snap

3 голосов
/ 19 ноября 2011

Я пытаюсь получить доступ к mongo, используя драйверы haskell mongodb (драйвер привязки, кажется, сломан для привязки> 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, так как действие монго происходит внутри монады ввода-вывода, и я хочу вытащить его обратно.Когда мое понимание нарушается, это результат компиляции этого соединения:

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

Извините, что опубликовал вопрос "Отправьте мне коды plz", но я в растерянности: где я иду не так?и как мне заставить это работать?

Ответы [ 2 ]

5 голосов
/ 21 ноября 2011

Вот ваша функция, снабженная сигнатурами типов. Я думаю, что это делает это довольно ясно, в чем проблема.

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», должно быть действием ввода-вывода. Последняя строка «результата покоя» нет. Одним из решений является добавление этой строки к 'трубе доступа мастер "дБ", так же, как вы сделали с поиском. Другое решение состоит в том, чтобы избежать дважды вызвать "трубу доступа ..." и заменить строку поиска следующим:

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

Затем замените строку «результат покоя» на «результат возврата»

То, что Дэниел говорит о строке поиска, не нуждающейся в liftIO, верно, но в этом случае это не имеет значения, потому что у IO есть экземпляр MonadIO. Так что, вероятно, так же легко хранить все материалы liftIO в одном блоке.

2 голосов
/ 19 ноября 2011

Я не эксперт MongoDB, поэтому я не уверен на 100% (и я не могу это проверить), но подозреваю, что вы получили liftIO не в том месте.У нас есть liftIO :: MonadIO m => IO a -> m a, поэтому мы должны применить liftIO к действиям, которые на самом деле IO, но которые мы хотим быть чем-то большим, чем IO.Я подозреваю, что access - это функция с типом возврата больше чем IO.Предполагая, что runIOE, close и rest все на самом деле имеют 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.)

...