我一直在努力想出一种简单直观的方法来使用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 }
任何指示我正确方向的建议都将受到赞赏。
答案 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
作品。