2012-04-01 52 views
3

我正在寫一個Happstack服務器,並且有一個MongoDB數據庫可以連接到。爲此,我做了一個函數來創建一個連接池用讀卡器擴展ServerPartT Monad

type MongoPool = Pool IOError Pipe 

withMongo :: (MongoPool -> IO a) -> IO() 
withMongo f = do 
    pool <- dbPool 
    f pool 
    killAll pool 

然後一個函數運行與創建池的Action

runDB :: (MonadIO m) => MongoPool -> Action IO a -> m (Either Failure a) 
runDB pool f = liftIO $ do 
    pipe <- runIOE $ aResource pool 
    access pipe master dbName f 

很顯然,這需要攜帶pool中的所有路線作爲參數。我想將其包裝到ReaderT中,以便runDB可以具有類似Action IO a -> ServerPart (Either Failure a)或更好的類型,Action IO a -> ServerPart a,其中故障將自動導致HTTP錯誤500。

對於如何實現這一點,我有點麻煩,我很想從Haskell monads和happstack有更多經驗的人那裏得到一些提示。

謝謝。

回答

3

通過這個問題,我發現了另一個非常好的提示,我已經建立了這個。它似乎工作正常,我想我會分享它:

type MongoPool = Pool IOError Pipe 

type DBServerPart a = ReaderT MongoPool (ServerPartT IO) a 

hostName = "127.0.0.1" 

dbName = "test" 

defaultPoolSize = 10 

runDB :: Action IO a -> DBServerPart (Either Failure a) 
runDB f = do 
    pool <- ask 
    liftIO $ do 
     pipe <- runIOE $ aResource pool 
     access pipe master dbName f 

withMongo :: DBServerPart a -> ServerPart a 
withMongo f = do 
    pool <- liftIO $ dbPool 
    a <- runReaderT f pool 
    liftIO $ killAll pool 
    return a 

dbPool = newPool fac defaultPoolSize 
    where fac = Factory { 
      newResource = connect $ host hostName, 
      killResource = close, 
      isExpired = isClosed 
     } 
+0

這看起來是正確的。另一種方法是,輸入DBServerPart a = ServerPartT(ReaderT MongoPool IO)a',然後使用'mapServerPartT'將其壓扁爲'ServerPartT IO'。這兩種解決方案之間的差別很小。如果您使用'HSX',雖然此方法將允許您將'XMLGenerator'實例用於'ServerPartT'。大多數情況下,你做它的方式並不重要。 – stepcut 2012-04-04 18:15:11