Skip to content

Instantly share code, notes, and snippets.

@akihiro4chawon
Forked from aya-eiya/getTerminals.hs
Created February 20, 2012 10:45
Show Gist options
  • Save akihiro4chawon/1868734 to your computer and use it in GitHub Desktop.
Save akihiro4chawon/1868734 to your computer and use it in GitHub Desktop.
指定したディレクトリを再帰的に探索して末端のパスのリストを返します。#haskell
monad transformer の練習をしてみました。
aya-eiya さんの作品では「引数として指定したファイル/ディレクトリが存在しない場合」を
別途エラー処理されていますが、関数の実行中にディレクトリの中のファイルが削除された場合に
(予期しない?)エラーが発生すると思われます。
この点が私の感性にそぐわなかったので、引数として存在しないディレクトリを指定した場合には
IOに包まれた空リストを返すように変更しました。
module Main where
import Control.Monad
import Control.Monad.Trans
import Control.Monad.Trans.List
import System.Directory
getAllFilesIn :: FilePath -> IO [FilePath]
getAllFilesIn path = runListT $ getAllFilesIn' path
where
getAllFilesIn' path = do
entry <- ListT $ getDirectoryContents path
guard $ entry /= "." && entry /= ".."
let fullPath = path ++ "/" ++ entry
isFile <- lift $ doesFileExist fullPath
if isFile
then return fullPath
else getAllFilesIn' fullPath
-- 意地でも do しないよ派だと、こんな感じか?
import Control.Monad
import Control.Applicative
import System.Directory
getAllFilesIn :: FilePath -> IO [FilePath]
getAllFilesIn path = (++) <$> children <*> descendants
where
contents = map ((path ++ "/") ++) <$> (\\ [".", ".."]) <$> getDirectoryContents path
children = filterM doesFileExist =<< contents
directories = filterM doesDirectoryExist =<< contents
descendants = join <$> (mapM getAllFilesIn =<< directories)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment