再帰的にディレクトリをたどる - その2
遅延評価をどうこうしようと思ったけど挫折。どっかを seq すりゃいいと思うんだけどなー。FilePath のリストを返さず、find 内で出力までやっちゃうようにすればすぐできそうなんだけど、それじゃ関数的じゃないよいなぁということで。
普通の find と比較していたら微妙に違うところがあったので、それを適当に修正した。
import System.Directory (doesFileExist, doesDirectoryExist, getDirectoryContents) import System.FilePath ((</>)) import Control.Monad (forM) import Control.Exception (catch, evaluate, SomeException) import System.Environment (getArgs) import Prelude hiding (catch) find :: FilePath -> IO [FilePath] find p = do isDir <- doesDirectoryExist p if isDir then find' p else return [p] where find' dir = do names <- getDirectoryContents dir let names' = filter (`notElem` [".", ".."]) names paths <- forM names' (\name -> find (dir </> name)) return (dir : concat paths) main = mapM_ putStrLn =<< find' =<< valid =<< head' =<< getArgs where head' xs = evaluate (head xs) `catch` (\e -> return (e::SomeException) >> return ".") valid p = do dir <- doesDirectoryExist p file <- doesFileExist p return (p, or [dir, file]) find' (_, False) = return [] find' (p, _) = find p
アクションを途中で終了する関数ってないのかなぁ。Bool が False のときには終了、Maybe が Nothing がときには終了的なもの。汎用的な guard というかなんというか。