Yesod:在 ghci 中运行“runDB”函数时键入实例错误

Posted

技术标签:

【中文标题】Yesod:在 ghci 中运行“runDB”函数时键入实例错误【英文标题】:Yesod: Type instance error while running `runDB` function in ghci 【发布时间】:2014-05-02 22:01:53 【问题描述】:

在 ghci 中加载脚手架站点后获得 runDB 返回的正确实例是什么?例如,在运行这句话时:

runDB $ selectList [UserName ==. "Renny"] []

错误是:

Couldn't match type `PersistMonadBackend
(YesodPersistBackend site0 (HandlerT site0 IO))'
with `persistent-1.3.0.6:Database.Persist.Sql.Types.SqlBackend'
The type variable `site0' is ambiguous
Possible fix: add a type signature that fixes these type variable(s)
Expected type: PersistMonadBackend
                 (YesodPersistBackend site0 (HandlerT site0 IO))
  Actual type: PersistEntityBackend User
In the second argument of `($)', namely
  `selectList [UserName ==. "Renny"] []'
In the expression: runDB $ selectList [UserName ==. "Renny"] []
In an equation for `it':
    it = runDB $ selectList [UserName ==. "Renny"] []

提前致谢

编辑: 我忘记了 Yesod Scaffold 的 runDB 返回一个处理程序,这导致我采用了这种解决方法(尽管我确信这是一个更好的解决方案):

xs <- runSqlite "MyProject.sqlite3" (selectList [UserName ==. "Renny"] []) 

"MyProject.sqlite3" 是 Sqlite 数据库的名称。

这不是一个通用的解决方案。根据文档,正如 post 所说,其他后端略有不同。

【问题讨论】:

如果用:set -XNoMonomorphismRestriction 关闭monomorphism restriction 会发生什么? 这是个好问题。我什至没有想过使用 GHCi 作为持久化的前端。 @nomen 感谢您的回复。我想我找到了一个解决方案(请参阅问题的最后编辑版本)。再见 【参考方案1】:

问题在于,与依赖环境状态的命令式语言不同,Haskell 依赖于显式(和隐式)状态传递。

当从 ghci 运行 runDB $ ... 时,您试图直接在 IO 中运行这个 sn-p,因此您没有引用您的应用程序状态(包括您的数据库连接)。类型错误通知您它The type variable 'site0' is ambiguous,因为它无法推断您尝试运行此语句的应用程序状态。

在 ghci 中,前缀 runSqlite "MyProject.sqlite3" 有效,因为您正在专门设置环境以针对正确的数据库运行,而 runSqlite 在 IO 中工作,这正是 ghci 想要的。

【讨论】:

以上是关于Yesod:在 ghci 中运行“runDB”函数时键入实例错误的主要内容,如果未能解决你的问题,请参考以下文章

如何在 REPL 中运行 Yesod 的数据库操作?

Haskell:Yesod 和 Esqueleto

“类型变量不明确”在 Haskell Yesod 中使用 Persistent

Yesod:卡在“七周内的七个 Web 框架”一书中

如何使用 Yesod/Persistent 访问两个不同的数据库服务器?

runDb 中的 MaybeT 和事务