2013-02-23 8 views
8

Próbowałem wymyślić prosty i intuicyjny sposób korzystania z baz danych z Haskell. Zrobiłem ten kod z Yesod book i próbowałem go wyczyścić, aby łatwiej było go zrozumieć i wykorzystać.Haskell/Persistent-Sqlite: "Brak instancji dla (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 

Ten kod prawie działa, ale pojawia się następujący błąd, którego nie udało się rozwiązać.

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 } 

Wszelkie sugestie wskazujące mi w dobrym kierunku zostałyby docenione.

+1

Potrzebujesz co najmniej 'runResourceT' wokół' updateDB' w 'main'. Nie jestem pewien, czy to wystarczy. –

+0

przepisywanie wiersza jako runResourceT $ updateDB "Frank Silver" 40 działał! Dziękuję Ci. Może chcesz opublikować swój komentarz jako odpowiedź? –

+4

Miałem ten problem również przy użyciu trwałych, ale miałem również błąd z wystąpieniem MonadLogger dla brak IO. Zostawiam to tutaj w nadziei, że pomoże to innej biednej duszy. Kluczem jest użycie 'runResourceT. Control.Monad.Logger.runNoLoggingT', ponieważ instancja programu MonadLogger IO została usunięta. – Khanzor

Odpowiedz

8

Z

main = do 
    updateDB "Frank Silver" 40 

rodzaj updateDB "Frank Silver" 40 wnioskuje się IO(), ponieważ jest to domyślny typ dla main (musi mieć typ IO a jakiegoś a). Ale z definicji jego typ jest określany jako MonadRescource m => m a dla niektórych a (prawdopodobnie a =(), ale nie jestem pewien), i nie ma instance MonadResource IO. Więc trzeba coś przekształcić updateDB do działania IO, normalny sposób, aby to zrobić jest runResourceT, który przekształca się w m aResourceT m a (tu m = IO), więc

main = runResourceT $ updateDB "Frank Silver" 40 

prace.

+0

Używam Haskell przez prawie rok i nadal uczę się korzystać z systemu typu. : D Jeszcze raz dziękuję za pomoc i odpowiedź. –