2013-02-23 15 views
8

Haskell ile veritabanlarını kullanmak için basit ve sezgisel bir yol bulmaya çalışıyorum. Bu kodu Yesod book'dan aldım ve bunu daha kolay anlayabilmek ve kullanabilmek için temizlemeye çalıştım.Haskell/Persistent-Sqlite: "(Control.Monad.Trans.Resource.MonadResource IO için örnek yok"

{-# 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 

Bu kod neredeyse çalışır, ama ben çözmek edemedik aşağıdaki hatayı alıyorum.

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 } 

Doğru yönde işaret eden önerileriniz için teşekkür ederiz. o main için varsayılan türü (bazı a için türünü IO a olması gerekir) beri

main = do 
    updateDB "Frank Silver" 40 

ile

+1

En azından 'main' içinde 'updateDB' etrafında en az bir' runResourceT 'gerekir. Gerçi bu yeterli mi, emin değilim. –

+0

satırı runResourceT $ updateDB olarak yeniden yazmak "Frank Silver" 40 çalıştı! Teşekkür ederim. Belki de yorumunuzu cevap olarak göndermek istersiniz? –

+4

Bu sorunu kalıcı olarak da kullanmıştım, ancak aynı zamanda IO'nun eksik olması için MonadLogger örneğindeki bir hata da vardı. Burada diğer bazı zavallı ruhlara yardım etmesini umut ediyorum. Anahtar 'runResourceT kullanmaktır. MonadLogger IO için örnek olarak Control.Monad.Logger.runNoLoggingT' kaldırıldı. – Khanzor

cevap

8

updateDB "Frank Silver" 40 türü, IO() olduğu anlaşılmaktadır. Ancak, tanımdan, türünün, a (muhtemelen a =(), ancak emin değilim) için MonadRescource m => m a olduğu ve instance MonadResource IO numarası olduğu anlaşılmaktadır. Bir IO eyleme updateDB dönüştürmek için bir şeye ihtiyacım Yani, bunu yapmak için, normal şekilde, bir m a (burada m = IO) içine ResourceT m a dönüştüren, hangi nedenle

main = runResourceT $ updateDB "Frank Silver" 40 

eser runResourceT olduğunu.

+0

Haskell'i neredeyse bir yıldır kullanıyorum ve hala tip sistemini nasıl kullanacağımı öğreniyorum. : D Yardımlarınız ve cevaplarınız için tekrar teşekkürler. –