2013-03-26 3 views
2

디렉토리를 통해 파일을 처리하고 결과를 데이터베이스에 저장하려고 시도하고 있지만 문제가 발생합니다.영구 및 IO 결합

I의 모습 할 노력하고있어의 간단한 예 :

{-# LANGUAGE QuasiQuotes, TemplateHaskell, TypeFamilies, OverloadedStrings #-} 
{-# LANGUAGE GADTs, FlexibleContexts #-} 
import Database.Persist 
import Database.Persist.Sqlite 
import Database.Persist.TH 
import System.Environment (getArgs) 
import System.Directory (canonicalizePath, getDirectoryContents, doesDirectoryExist, doesFileExist) 
import System.FilePath (combine, takeExtension) 
import Control.Monad (filterM, mapM_) 
import Control.Monad.IO.Class (liftIO) 

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistUpperCase| 
File              
    path String 
    deriving (Show) 
|] 
main :: IO() 
main = do 
    args <- getArgs 
    path <- canonicalizePath $ head args 
    runSqlite "files.sqlite" $ do 
    runMigration migrateAll 
    liftIO $ processDirectory path 
    return() 

processDirectory path = files >>= mapM_ processFile >> 
         directories >>= mapM_ processDirectory 
    where contents = getDirectoryContents path >>= 
        return . map (combine path) . filter (`notElem` [".", ".."]) 
     directories = contents >>= filterM doesDirectoryExist 
     files = contents >>= filterM doesFileExist 

processFile path = insert $ File path 

(가) 위, 그러나 컴파일하지 않는 대신 결과 :

No instance for (PersistStore IO) 
     arising from a use of `processFile' 
    Possible fix: add an instance declaration for (PersistStore IO) 
    In the first argument of `mapM_', namely `processFile' 
    In the second argument of `(>>=)', namely `mapM_ processFile' 
    In the first argument of `(>>)', namely 
     `files >>= mapM_ processFile' 
Failed, modules loaded: none. 

이 나에게 의미가 있습니다, processFile은 단지 insert를 호출 한 것이기 때문에, PersistStore 모나드의 어느 부분 (오른쪽?)은 IO가 아니기 때문입니다. 나는 내가 필요한 것은 모나드 변압기라고 생각하지만,이 시점에서 나는 벽돌 벽에 뛰어 들었다. 아마 이것은 내가 잘못된 나무를 짖고 있다는 것을 의미 할 것이다. 당신이 그것의 에는 processFile 외부를 떠날 코드를 재 배열 할 필요가 있도록하지을 한 것은 liftIO으로 둘러싸인 원하는

답변

7

는 데이터베이스 작업입니다.

코드를 컴파일하는 가장 간단한 변경 사항은 다음과 같습니다. 나는 당신에게 그것을 정리할 수 있도록 남겨 두어 그것이 어떻게 진행되고 있는지 명확하게 보여줄 것입니다!

{-# LANGUAGE QuasiQuotes, TemplateHaskell, TypeFamilies, OverloadedStrings #-} 
{-# LANGUAGE GADTs, FlexibleContexts #-} 
import Database.Persist 
import Database.Persist.Sqlite 
import Database.Persist.TH 
import System.Environment (getArgs) 
import System.Directory (canonicalizePath, getDirectoryContents, doesDirectoryExist, doesFileExist) 
import System.FilePath (combine, takeExtension) 
import Control.Monad (filterM, mapM_) 
import Control.Monad.IO.Class (liftIO) 

share [mkPersist sqlSettings, mkMigrate "migrateAll"] [persistUpperCase| 
File              
    path String 
    deriving (Show) 
|] 
main :: IO() 
main = do 
    args <- getArgs 
    path <- canonicalizePath $ head args 
    runSqlite "files.sqlite" $ do 
    runMigration migrateAll 
    processDirectory path 
    return() 

processDirectory path = liftIO files >>= mapM_ processFile >> 
         liftIO directories >>= mapM_ processDirectory 
    where contents = getDirectoryContents path >>= 
        return . map (combine path) . filter (`notElem` [".", ".."]) 
     directories = contents >>= filterM doesDirectoryExist 
     files = contents >>= filterM doesFileExist 

processFile path = insert $ File path 
+0

아, 물론 liftIO를 찾았 으면 분명했을 것입니다. 나는 내가 너무 오랫동안 그것을 꼼짝 않고 바라 보았다고 생각한다. 감사! –