尝试使用持久性时,没有Control.Monad.Logger.MonadLogger的实例

时间:2013-12-30 21:59:15

标签: database haskell web-applications logging persistent

我正在使用scottypersistent构建一个网络应用,并且遇到了一些麻烦。这是我的代码:

runDb :: SqlPersist (ResourceT IO) a -> IO a
runDb query = runResourceT . withSqliteConn "dev.app.sqlite3" . runSqlConn $ query

readMessage :: KeyBackend (PersistEntityBackend Post) Post -> IO (Maybe Post)
readMessage postID = runDb $ get postID

我收到此错误消息:

Message.hs:30:30:
No instance for (Control.Monad.Logger.MonadLogger IO)
  arising from a use of `get'
Possible fix:
  add an instance declaration for
  (Control.Monad.Logger.MonadLogger IO)
In the second argument of `($)', namely `get postID'
In the expression: runDb $ get postID
In an equation for `readMessage':
    readMessage postID = runDb $ get postID

我发现了this个问题,但接受的答案是使用旧版monad-logger,这也会迫使我使用许多其他软件包的旧版本scotty和{{1包含,我不想那样做。另一个答案建议使用persistent,我无法使用它。我无法弄清楚要把它放到什么样的地方。

1 个答案:

答案 0 :(得分:9)

runNoLoggingT的类型为

runNoLoggingT :: NoLoggingT m a -> m a
只要上面的MonadLoggerm的实例,

就是有效的MonadIO。以下所有堆栈都是MonadIO

的实例
SqlPersist (ResourceT IO)
            ResourceT IO
                      IO

因此,以下所有堆栈都是MonadLogger

的有效实例
NoLoggingT (SqlPersist (ResourceT IO))
SqlPersist (NoLoggingT (ResourceT IO))
SqlPersist (ResourceT (NoLoggingT IO))

我建议第三个,然后我们只需编辑

runDb :: SqlPersist (ResourceT (NoLoggingT IO)) a -> IO a
runDb = runNoLoggingT 
      . runResourceT 
      . withSqliteConn "dev.app.sqlite3" 
      . runSqlConn