2013-07-02 25 views
1

Я пытаюсь заставить мой MongoDB работать в Haskell. Я использовал this tutorial в качестве отправной точки. Когда я делаю эти команды в прелюдии, я получаю список коллекций:Разница между прелюдией и дадом с MongoDB

pipe <- runIOE $ connect $ Host "XXXXX.mongolab.com" $ PortNumber 33317 
access pipe master <databaseName> $ auth <username> <password> 
access pipe master <databaseName> allCollections 

Однако, когда я пытаюсь положить, что в Йесод Handler, это не компиляции. У меня есть

getActivityR :: Handler Import.Value 
getActivityR = do 
    pipe <- runIOE $ connect $ Host "XXXXX.mongolab.com" $ PortNumber 33317 
    access pipe master <databaseName> $ auth <username> <password> 
    access pipe master <databaseName> allCollections 
    returnJson $ object ["activity" .= ("abc" :: Text)] 

ReturnJson на самом деле просто, чтобы сообщить мне, что я завершил метод. В конце концов он вернет список действий.

Ошибки я получаю:

Couldn't match type `IO' with `HandlerT App IO' 

    Expected type: HandlerT App IO Pipe 

     Actual type: IO Pipe 

    In a stmt of a 'do' block: 

     pipe <- runIOE 

       $ connect $ Host "XXXXXX.mongolab.com" $ PortNumber 33317 

Так, что разница между Prelude/GHCi и моим Йесодом кодом строятся заговорщиками?

+4

Я мало знаю об Yesod, но GHCi запускает эту команду в монаде IO, в то время как ваш код Yesod, по-видимому, запускает его в монаде «HandlerT App IO». Попробуйте 'pipe <- liftIO $ runIOE $ ...' – Fixnum

+0

Я думаю, что комментарий Fixnum на самом деле является ответом. –

+0

@Fixnum Это похоже на исправление ошибки сборки. Благодарю. Если вы наберете его в качестве ответа, я соглашусь с ним и получу несколько моментов :) – taylonr

ответ

3

Проблема в том, что GHCi запускает ваш код в монаде IO, в то время как ваша функция находится в монаде HandlerT App IO. Но HandlerT является монадным трансформатором над монашкой IO, поэтому вы можете использовать lift, чтобы «продвигать» ваше действие IO на действие HandlerT App IO. Тип подъемника:

lift :: (MonadTrans t, Monad m) => m a -> t m a 

В вашем случае, t должен быть HandlerT App и m должен быть IO. Так правильный код выглядит следующим образом:

getActivityR :: Handler Import.Value 
getActivityR = do 
    pipe <- lift $ runIOE $ connect $ Host "XXXXX.mongolab.com" $ PortNumber 33317 
    access pipe master <databaseName> $ auth <username> <password> 
    access pipe master <databaseName> allCollections 
    returnJson $ object ["activity" .= ("abc" :: Text)] 

Я не знаю, что ваш access, поэтому я не могу сказать, нужно ли вам лифт там тоже или нет.

Для вашего особого случая, есть также liftIO, который походит lift, но поднимает прямо к IO, а не только к следующему «слой» в вашем стеке монад трансформаторов, так что вы должны использовать его:

pipe <- liftIO $ runIOE $ connect $ Host "XXXXX.mongolab.com" $ PortNumber 33317 

Если вы хотите узнать больше об этой теме, вы должны искать «монадные трансформаторы».

Смежные вопросы