2013-05-23 17 views
7

私はHaskellのフォルダのすべてのサブフォルダを列挙したいと思います。すべてのフォルダの内容を取得するのは簡単ですが、getDirectoryContentsの機能があります。しかし、どうすればそれらをフィルタリングできますか? getDirectoryContentsIO [FilePath]を返し、filter[a]と予想しているため、これら2つを直接組み合わせることはできません。 (もちろん、私はモナドで新鮮な魚だとdo記法を。)フォルダのすべてのサブフォルダを見つける方法を教えてください。

getAllFolders :: FilePath -> IO [FilePath] 
getAllFolder path = do 
    allItems <- getDirectoryContents path 
    -- now what? the predicate is doesDirectoryExist 

答えて

7

タイプIO [FilePath]、あなたは結果を結合することによりFilePath秒のプレーンなリストを取得し、

getAllFolders path = do 
    contents <- getDirectoryContents path 
    -- do something with contents now, it's a plain [FilePath] 

問題があることです述語doesDirectoryExistのタイプはFilePath -> IO Boolです。このようなことのために、名前にディレクトリの内容を結合することなく、

getAllFolders path = getDirectoryContents path >>= filterM doesDirectoryExist 

とポイントフリーが、Control.Monadで定義された

ghci> :t Control.Monad.filterM 
Control.Monad.filterM :: Monad m => (a -> m Bool) -> [a] -> m [a] 

filterMので

getAllFolders path = do 
    contents <- getDirectoryContents path 
    filterM doesDirectoryExist contents 

ですか:

getAllFolders = getDirectoryContents >=> filterM doesDirectoryExist 
+0

ありがとう!相対的/絶対的なファイルパスには別の問題がありますが、私はそれを理解することができます。 – zoul

+2

このような相対的な問題の問題は、私が常に周りを回るために図書館を発明したところまで、私を引きつけています!また、 'getDirectoryContents'は常に' .'と '..'を返します。これは面倒です。 – MathematicalOrchid

+0

'> =>' mmmm。 '> =>'が好きです。 – AndrewC

3

Control.Monadが提供するfilterMのように見えるの答えです:問題はgetDirectoryContentsはリターンを持っているということではありません

getAllFolders :: FilePath -> IO [FilePath] 
getAllFolders path = do 
    allItems <- getDirectoryContents path 
    justFolders <- filterM doesDirectoryExist allItems 
    return justFolders 
+0

正しい。最後の2行を 'filterM doesDirectoryExist allItems'にまとめることもできます。' x < - foo; return x'は 'foo'と同じです。 – hammar

+0

よかった、ありがとう。 – zoul

関連する問題