2013-02-23 15 views
8

Ho cercato di trovare un modo semplice e intuitivo per utilizzare i database con Haskell. Ho preso questo codice dallo Yesod book e ho provato a ripulirlo in modo che fosse più facile da capire e da usare.Haskell/Persistent-Sqlite: "Nessuna istanza per (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 

Questo codice quasi opere, ma ottengo il seguente errore, che non sono stato in grado di risolvere.

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 } 

Qualsiasi suggerimento che mi indicasse la giusta direzione sarebbe apprezzato.

+1

È necessario almeno un 'runResourceT' attorno a' updateDB' in 'main'. Non sono sicuro che sarà abbastanza, comunque. –

+0

riscrivendo la riga come runResourceT $ updateDB "Frank Silver" ha funzionato 40 volte! Grazie. Forse ti piacerebbe pubblicare il tuo commento come risposta? –

+4

Ho avuto questo problema anche usando persistente, ma ho anche avuto un errore con un'istanza di MonadLogger per I/O mancante. Lo lascio qui nella speranza che aiuti qualche altra povera anima. La chiave è usare 'runResourceT. Control.Monad.Logger.runNoLoggingT', poiché l'istanza per MonadLogger IO è stata rimossa. – Khanzor

risposta

8

Con

main = do 
    updateDB "Frank Silver" 40 

il tipo di updateDB "Frank Silver" 40 si inferisce essere IO(), dato che è il tipo predefinito per main (deve avere tipo IO a per qualche a). Ma dalla definizione, il suo tipo è dedotto per essere MonadRescource m => m a per alcuni a (probabilmente a =(), ma non sono sicuro), e non c'è instance MonadResource IO. Quindi, avete bisogno di qualcosa di trasformare la updateDB a un IO azione, il modo normale per farlo è runResourceT, che trasforma un ResourceT m a in un m a (qui m = IO), così

main = runResourceT $ updateDB "Frank Silver" 40 

opere.

+0

Utilizzo Haskell da quasi un anno e sto ancora imparando come utilizzare il sistema di tipi. : D Grazie ancora per il tuo aiuto e risposta. –

Problemi correlati