Расширение монады ServerPartT с помощью средства чтения

Я пишу сервер Happstack, и у меня есть база данных MongoDB для подключения. Для этого я сделал функцию для создания пула соединений

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 и happstack.

Спасибо.


person Lanbo    schedule 01.04.2012    source источник


Ответы (1)


Через этот вопрос я нашел еще один с очень хорошей подсказкой, и я построил его. Кажется, он работает нормально, и я решил поделиться им:

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
        }
person Lanbo    schedule 01.04.2012
comment
Мне это кажется правильным. Другой вариант — сделать type DBServerPart a = ServerPartT (ReaderT MongoPool IO) a, а затем использовать mapServerPartT, чтобы сгладить его до ServerPartT IO. Между двумя решениями небольшая разница. Хотя этот метод позволит вам использовать экземпляр XMLGenerator для ServerPartT, если вы используете HSX. В большинстве случаев не имеет значения, каким образом вы это сделаете. - person stepcut; 04.04.2012