我正在尝试使用Snap创建一个简单的Web应用程序。我希望有一个全局的MongoDB连接,我可以在处理程序中使用它。
我在appInit
中打开此连接,该连接有效。
data App = App { _mongoDB :: Pipe -- connection
}
appInit :: SnapletInit App App
appInit = makeSnaplet "site" "My Site" Nothing $ do
db <- liftIO $ do
pipe <- runIOE $ connect (host "127.0.0.1")
return pipe
return $ App db
但是,我不知道如何从处理程序访问此连接(_mongoDB
)。我尝试了几件事,包括以下内容,但每次都会出现类型错误。
watchHandler :: Handler App App ()
watchHandler = do
res <- liftIO $ do
pipe <- gets _mongoDB -- type error
results <- access pipe master "db" (find $ select [] "movies")
return results
writeBS "test"
它给了我以下错误:
No instance for (MonadState App IO)
arising from a use of `gets'
Possible fix: add an instance declaration for (MonadState App IO)
In a stmt of a 'do' block: pipe <- gets _mongoDB
In the second argument of `($)', namely
`do { pipe <- gets _mongoDB;
results <- access pipe master "db" (find $ select [] "movies");
return results }'
In a stmt of a 'do' block:
res <- liftIO
$ do { pipe <- gets _mongoDB;
results <- access pipe master "db" (find $ select [] "movies");
return results }
它让我感到困惑。如何从处理程序访问我的MongoDB连接?
答案 0 :(得分:3)
liftIO
块仅用于IO操作,访问应用程序状态需要在Handler
monad本身中完成。
watchHandler :: Handler App App ()
watchHandler = do
pipe <- gets _mongoDB
res <- liftIO $ do
results <- access pipe master "db" (find $ select [] "movies")
return results
writeBS "test"
此外,绑定值然后立即返回它是多余的。你可以写:
watchHandler :: Handler App App ()
watchHandler = do
pipe <- gets _mongoDB
res <- liftIO $ access pipe master "db" (find $ select [] "movies")
writeBS "test"