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

Posted

技术标签:

【中文标题】尝试使用持久性时没有 Control.Monad.Logger.MonadLogger 的实例【英文标题】:No instance for Control.Monad.Logger.MonadLogger when attempting to use persistent 【发布时间】:2014-01-17 20:29:14 【问题描述】:

我正在使用 scottypersistent 构建一个 Web 应用程序,但在编译时遇到了一些麻烦。这是我的代码:

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,这也将迫使我使用许多其他软件包的旧版本,包括scottypersistent,我不这样做'不想那样做。另一个答案建议使用runNoLoggingT,我无法正常工作。我不知道把它放在哪里进行类型检查。

【问题讨论】:

【参考方案1】:

runNoLoggingT 有类型

runNoLoggingT :: NoLoggingT m a -> m a

只要上面的mMonadIO 的一个实例,它就是一个有效的MonadLogger。以下所有堆栈都是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

【讨论】:

我猜你必须将值包装在 NoLoggingT 构造函数中

以上是关于尝试使用持久性时没有 Control.Monad.Logger.MonadLogger 的实例的主要内容,如果未能解决你的问题,请参考以下文章

尝试以下发现的实现后,没有可用于“myDB”的持久性提供程序

`ap zip tail` 表达式是如何工作的

Haskell拓展篇三:Fix和Fixpoint

UITableView状态持久性中的复选框

有没有办法在继承期间持久化装饰器?

持久化对象时没有可用的事务性 EntityManager