再帰的にディレクトリをたどる
いわゆる find。forM ははじめて使った。ただこの実装だと、遅延評価の影響でメモリを馬鹿食いする。次回はこれの改善かな。
しかし例外 API をはじめてまともに使ったけども、とても使いやすいとは言えないな。\e を \_ として評価しないようにしても、型があいまいだと GHC にゴネられる。まぁ型レベルの話は評価するしないには関係ないのだろうけどさ。
import System.Directory (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 (concat paths) main = mapM_ putStrLn =<< find =<< head' =<< getArgs where head' xs = evaluate (head xs) `catch` (\e -> return (e::SomeException) >> return ".")