2013-05-23 14 views
7

Chciałbym wyliczyć wszystkie podfoldery folderu w Haskell. Uzyskanie całej zawartości folderu jest łatwe, istnieje funkcja getDirectoryContents. Ale jak je odfiltrować? Od getDirectoryContents zwraca IO [FilePath] i filter spodziewa [a], nie mogę umieścić te dwa bezpośrednio ze sobą. (. Oczywiście, jestem świeżą rybę z monad i zrób notacji)Jak znaleźć wszystkie podfoldery folderu?

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

Odpowiedz

7

Problemem jest to, że nie ma powrotu getDirectoryContents Typ IO [FilePath], masz zwykły listę FilePath s poprzez wiązanie wynik,

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

problemem jest to, że predykat doesDirectoryExist ma typ FilePath -> IO Bool. Dla takich rzeczy, nie ma

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

filterM zdefiniowane w Control.Monad, więc

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

lub bez wiązania zawartość katalogu do nazwy,

getAllFolders path = getDirectoryContents path >>= filterM doesDirectoryExist 

i wskaż darmo :

getAllFolders = getDirectoryContents >=> filterM doesDirectoryExist 
+0

Dziękujemy! Dodatkowy problem dotyczy względnych/bezwzględnych ścieżek plików, ale mogę to zrozumieć. – zoul

+2

Ten problem ze względnymi ścieżkami nieustannie mnie podnieca - do punktu, w którym wymyśliłem bibliotekę, aby ją obejść! Również 'getDirectoryContents' zawsze zwraca' .' i '..', co jest denerwujące. – MathematicalOrchid

+0

'> =>' mmmm. Lubimy '> =>'. – AndrewC

3

Wygląda filterM oferowanych przez Control.Monad jest odpowiedź:

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

Prawidłowo. Możesz także połączyć ostatnie dwie linie w po prostu 'filterM doesDirectoryExist allItems', ponieważ' x <- foo; return x' to to samo, co po prostu 'foo'. – hammar

+0

Świetnie, dziękuję. – zoul

Powiązane problemy