2013-02-23 8 views
8

Ich habe versucht, eine einfache und intuitive Möglichkeit zu finden, Datenbanken mit Haskell zu verwenden. Ich habe diesen Code aus der Yesod book genommen und versucht, es zu bereinigen, so dass es einfacher zu verstehen und zu verwenden ist.Haskell/Persistent-Sqlite: "Keine Instanz für (Control.Monad.Trans.Resource.MonadResource IO)"

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

Dieser Code fast funktioniert, aber ich bekomme die folgende Fehlermeldung, die ich zu lösen nicht in der Lage gewesen.

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 } 

Alle Vorschläge, die mich in die richtige Richtung weisen würden geschätzt.

+1

Sie benötigen mindestens eine 'runResourceT' um' 'updateDB' in' main'. Ich bin mir nicht sicher, ob das ausreichen wird. –

+0

Umschreiben der Zeile als runResourceT $ updateDB "Frank Silver" 40 hat funktioniert! Vielen Dank. Vielleicht möchten Sie Ihren Kommentar als Antwort posten? –

+4

Ich hatte dieses Problem mit Persistent auch, aber ich hatte auch einen Fehler mit einer Instanz von MonadLogger für IO fehlt. Ich verlasse es hier in der Hoffnung, dass es einer anderen armen Seele hilft. Der Schlüssel ist 'runResourceT zu verwenden. Control.Monad.Logger.runNoLoggingT', da die Instanz für MonadLogger IO entfernt wurde. – Khanzor

Antwort

8

Mit

main = do 
    updateDB "Frank Silver" 40 

die Art der updateDB "Frank Silver" 40 wird gefolgert IO() zu sein, denn das ist der Typ Standard ist für main (es muss Typ haben IO a für einige a). Aber aus der Definition wird sein Typ MonadRescource m => m a für einige a (wahrscheinlich a =(), aber ich bin mir nicht sicher), und es gibt keine instance MonadResource IO. Also man etwas braucht die updateDB zu einer IO die Tat umzusetzen, ist der normale Weg, das zu tun runResourceT, die eine ResourceT m a in eine m a (hier m = IO) transformiert, so

main = runResourceT $ updateDB "Frank Silver" 40 

funktioniert.

+0

Ich benutze Haskell seit fast einem Jahr und lerne immer noch, wie man das Typsystem benutzt. : D Danke nochmal für deine Hilfe und antworte. –

Verwandte Themen