Haskell / Persistent-Sqlite:“没有(Control.Monad.Trans.Resource.MonadResource IO)的实例”

时间:2013-02-23 23:49:02

标签: database haskell yesod

我一直在努力想出一种简单直观的方法来使用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 }

任何指示我正确方向的建议都将受到赞赏。

1 个答案:

答案 0 :(得分:9)

使用

main = do
    updateDB "Frank Silver" 40

updateDB "Frank Silver" 40的类型被推断为IO (),因为这是main的默认类型(对于某些IO a,它必须具有a类型) 。但是根据定义,对于某些MonadRescource m => m a(可能是a,它的类型被推断为a = (),但我不确定),并且没有instance MonadResource IO。因此,您需要将updateDB转换为IO操作,正常的方法是runResourceT,它会将ResourceT m a转换为m a(这里m = IO),所以

main = runResourceT $ updateDB "Frank Silver" 40

作品。