2013-02-23 2 views
8

저는 Haskell에서 데이터베이스를 사용하는 간단하고 직관적 인 방법을 고안해 왔습니다. 이 코드를 Yesod book에서 가져 와서 이해하고 사용하기 쉽도록 정리하려고했습니다.Haskell/Persistent-Sqlite : "(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 

이 코드 거의 작품,하지만 난 해결하지 못하고 다음과 같은 오류가 발생합니다.

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 } 

올바른 방향으로 나를 가리키는 모든 의견을 보내 주시면 감사하겠습니다. 그 main의 기본 유형 (이 일부 a에 대한 유형 IO a이 있어야합니다)이 이후

main = do 
    updateDB "Frank Silver" 40 

+1

'main'의'updateDB' 주위에 적어도'runResourceT '가 필요합니다. 그래도 충분할지 모르겠다. –

+0

runResourceT $ updateDB "Frank Silver"40으로 행을 다시 작성했습니다! 고맙습니다. 답변으로 의견을 게시하고 싶습니까? –

+4

나는 persistent를 사용하여이 문제를 겪었지만, IO 누락을 위해 MonadLogger 인스턴스에 오류가 발생했습니다. 나는 다른 가난한 영혼을 돕기를 희망하며 이곳을 떠난다. 열쇠는 runResourceT를 사용하는 것입니다. Control.Monad.Logger.runNoLoggingT', MonadLogger IO 인스턴스가 제거되었습니다. – Khanzor

답변

8

updateDB "Frank Silver" 40의 유형, IO() 것으로 추정된다. 그러나이 정의에서 그 유형은 (아마도 a =()이지만 아마도 MonadRescource m => m a)으로 추론되며, 어떤 것이 든 instance MonadResource IO이 아닙니다. 당신이 IO 행동에 updateDB를 변환하는 뭔가가 필요 그래서, 그 작업을 수행하는 일반적인 방법은, m a (여기 m = IO)에 ResourceT m a 변환하는, 그래서

main = runResourceT $ updateDB "Frank Silver" 40 

작품 runResourceT입니다.

+0

저는 거의 1 년 동안 하스켈을 사용 해왔고, 저는 여전히 타입 시스템을 사용하는 방법을 배우고 있습니다. : D 귀하의 도움과 회신에 다시 한번 감사드립니다. –