7

我想枚举 Haskell 中一个文件夹的所有子文件夹。获取所有文件夹内容很容易,有一个 getDirectoryContents功能。但是我该如何过滤它们呢?由于getDirectoryContents返回 aIO [FilePath]filter期望[a],我不能将这两者直接放在一起。(显然,我是一条有 monads 和 do-notation 的新鲜鱼。)

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

2 回答 2

7

问题不在于getDirectoryContents有返回类型IO [FilePath],你FilePath通过绑定结果得到一个简单的 s 列表,

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

问题是谓词doesDirectoryExist具有类型FilePath -> IO Bool。对于这样的事情,有

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

filterM中定义Control.Monad,所以

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

或者,不将目录的内容绑定到名称,

getAllFolders path = getDirectoryContents path >>= filterM doesDirectoryExist

并且无点:

getAllFolders = getDirectoryContents >=> filterM doesDirectoryExist
于 2013-05-23T14:26:59.507 回答
3

看起来filterM提供Control.Monad的答案是:

getAllFolders :: FilePath -> IO [FilePath]
getAllFolders path = do
    allItems <- getDirectoryContents path
    justFolders <- filterM doesDirectoryExist allItems
    return justFolders
于 2013-05-23T14:24:57.717 回答