2013-07-02 35 views
1

我想讓我的MongoDB在Haskell中工作。我以this tutorial爲起點。當我在前奏執行這些命令,我​​得到收藏的列表:前奏和yesod與MongoDB的區別

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

然而,當我試圖把在耶索德處理程序,它不是編譯。我有

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 

那麼,什麼是前奏/ GHCI和我耶索德碼之差被驚天動地建的?

+4

我對Yesod知之甚少,但GHCi在'IO' monad中運行此命令,而您的Yesod代碼顯然是在'HandlerT App IO' monad中運行的。試試'pipe < - liftIO $ runIOE $ ...' – Fixnum

+0

我認爲@ Fixnum的評論其實就是答案。 –

+0

@Fixnum這似乎解決了構建錯誤。謝謝。如果你將它作爲答案輸入,我會接受它並讓你有一些觀點:) – taylonr

回答

3

問題是GHCi在你的代碼中運行你的代碼,而你的函數在HandlerT App IO monad中。但HandlerT是單粒變換器,因此可以使用liftIO操作「升級」爲HandlerT App IO操作。該類型電梯的是:

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

在你的情況,t必須HandlerT Appm必須是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 

如果你想知道更多關於這個話題,你應該尋找「monad變壓器」。