【问题标题】:Haskell / Persistent-Sqlite: "No instance for (Control.Monad.Trans.Resource.MonadResource IO)"Haskell / Persistent-Sqlite:“(Control.Monad.Trans.Resource.MonadResource IO)没有实例”
【发布时间】:2013-02-09 10:09:52
【问题描述】:

我一直在尝试想出一种简单直观的方式来使用 Haskell 中的数据库。我从Yesod book 获取了这段代码,并尝试对其进行清理,以便更容易理解和使用。

{-# LANGUAGE QuasiQuotes, TemplateHaskell, TypeFamilies, OverloadedStrings #-}
{-# LANGUAGE GADTs, FlexibleContexts #-}

import Database.Persist
import Database.Persist.Sqlite (withSqliteConn, runSqlConn, runMigration)
import Database.Persist.TH (share, mkPersist, mkMigrate, sqlSettings, persist)

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persist|
Person                              -- Table name
    name String                     -- String value
    age Int Maybe                   -- Numerical value
|]

updateDB x y = withSqliteConn "data.db" $ runSqlConn $ do
    runMigration migrateAll         -- Creates "Person" table if one doesn't exist
    insert $ Person x $ Just y      -- Inserts values into .db file

main = do
    updateDB "Frank Silver" 40      -- adds name "Frank Silver" and age "40" to data.db file

此代码几乎有效,但我收到以下我无法解决的错误。

No instance for (Control.Monad.Trans.Resource.MonadResource IO)
      arising from a use of `updateDB'
    Possible fix:
      add an instance declaration for
      (Control.Monad.Trans.Resource.MonadResource IO)
    In a stmt of a 'do' block: updateDB "Frank Silver" 40
    In the expression: do { updateDB "Frank Silver" 40 }
    In an equation for `main': main = do { updateDB "Frank Silver" 40 }

任何为我指明正确方向的建议将不胜感激。

【问题讨论】:

  • main 中的updateDB 周围至少需要一个runResourceT。不过,我不确定这是否足够。
  • 将行重写为 runResourceT $ updateDB "Frank Silver" 40 工作!谢谢你。也许您想发表您的评论作为答案?
  • 我在使用持久化时也遇到了这个问题,但是我也有一个 MonadLogger 实例的错误,因为 IO 丢失。我把它留在这里,希望它能帮助其他一些可怜的灵魂。关键是使用runResourceT . Control.Monad.Logger.runNoLoggingT,因为 MonadLogger IO 的实例已被删除。

标签: database haskell yesod


【解决方案1】:

main = do
    updateDB "Frank Silver" 40

updateDB "Frank Silver" 40 的类型被推断为IO (),因为这是main 的默认类型(对于某些a,它必须具有IO a 类型)。但是从定义上,对于一些a(可能是a = (),但我不确定)推断它的类型是MonadRescource m => m a,并没有instance MonadResource IO。所以你需要一些东西来将updateDB 转换为IO 动作,通常的方法是runResourceT,它将ResourceT m a 转换为m a(这里是m = IO),所以

main = runResourceT $ updateDB "Frank Silver" 40

有效。

【讨论】:

  • 我使用 Haskell 已经快一年了,我还在学习如何使用类型系统。 :D 再次感谢您的帮助和回复。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多