2017-12-11 6 views
3

これは初心者の質問です。おそらくこれは絶望的な重複してHaskell:1つの共通リストからファイルのリストとディレクトリのリストを作成する方法

getFilesAndDirs :: [FilePath] -> ([FilePath], [FilePath]) 
getFilesAndDirs paths = 
    let ... 
    in (dirs, files) 

、私はちょうど適切なキーワードを欠場:私は、ファイルやディレクトリのリストのリストにファイルとディレクトリのリストを分離するとします。 これを行う(そして呼び出す)正しい方法は何ですか?

ファイルとディレクトリはランダムに発生します。

+0

'Data.List'には、あなたが求めるもののように見える' partition'という関数があります。 –

+0

@ MarkSeemann:ここでの問題は、述語がモナドであることです( 'FilePath - > IO Bool') –

+0

関連:https://stackoverflow.com/q/31419429/126014 –

答えて

2

Data.Listパッケージには、述語に基づいてa Sの二つのリストのタプルにaのリストを分割partition :: (a -> Bool) -> [a] -> ([a],[a])機能を持っています。

ただし、ファイルがディレクトリであるかどうかを確認するときは、isDirectory :: FilePath -> IO Boolを使用します(IO BoolBoolと等しくないため、これを直接述語として使用できません)。

私たちは、しかし、私たち自身のpartitionMを書き、1という使用することができます。

import Data.Bool(bool) 
import Data.Foldable(foldrM) 

partitionM :: (Foldable t, Monad m) => (a -> m Bool) -> t a -> m ([a], [a]) 
partitionM p = foldrM (selectM p) ([],[]) 

selectM :: Monad m => (a -> m Bool) -> a -> ([a], [a]) -> m ([a], [a]) 
selectM p x (ts,fs) = p x >>= return . bool (ts, x:fs) (x:ts,fs) 

我々はそれが好きで使用することができます:我々は実行する必要があるため、それは、IO ([FilePath], [FilePath])であること

import System.Directory(isDirectory) 

getFilesAndDirs :: [FilePath] -> IO ([FilePath], [FilePath]) 
getFilesAndDirs = partitionM isDirectory

注意I/Oを使用して、パスが実際にディレクトリであるかどうか(ファイルではない)を確認します。

+0

ありがとう! –

+0

'selectM'の結果の型にモナドがないのですか?また、それに見合った怠惰なパターンマッチはありますか? –

+0

@SebastianRedl:ありがとう。実際にはそれほど価値がないでしょう:) –

0
module SeparateFiles where 
    import Data.String 
    import System.FilePath.Posix 


    type Path = FilePath 
    getFilesAndDirs :: Path -> [(Path,Path)] 
    getFilesAndDirs path = [splitFileName path] 

FilePath抽出をファイルとディレクトリに分割したいと思っています。私はあなたに非常に短い例を提供します。

2

do表記を使用して、プログラムの不完全な部分を調整し、partitionなどの組み込み(純粋な)関数を使用して実際の作業を行うことができます。ここでは例です:これは値の不純なリストを取得するには、内蔵mapM機能を使用していることを

module Q47755054 (getFilesAndDirs) where 

import Data.List (partition) 
import Data.Bifunctor (bimap) 
import System.Directory (doesDirectoryExist) 

tagPath :: FilePath -> IO (FilePath, Bool) 
tagPath path = do 
    isDirectory <- doesDirectoryExist path 
    return (path, isDirectory) 

getFilesAndDirs :: [FilePath] -> IO ([FilePath], [FilePath]) 
getFilesAndDirs paths = do 
    taggedPaths <- mapM tagPath paths 
    return $ bimap (fmap fst) (fmap fst) $ partition snd taggedPaths 

お知らせ(IO [(FilePath, Bool)])が、原因do構文へと<-が結合、taggedPathsは純粋のように「見えます」値([(FilePath, Bool)])ですので、partitionに渡すことができます。 は、モジュールによってエクスポートされない単なるモジュールレベルヘルパ関数であることに注意してください。さらに、tagPathは、モジュールによってエクスポートされないヘルパー関数です。

関連する問題