I wrote this program that recursively prints all the files and directories starting at the current directory:
import Data.Tree (Tree (..)) import System.Directory (doesDirectoryExist, getCurrentDirectory, getDirectoryContents) main :: IO () main = do currentDirectory <- getCurrentDirectory tree <- tree currentDirectory "." printTree 0 tree printTree :: Int -> Tree FilePath -> IO () printTree indent tree = do putStrLn $ (replicate indent ' ' ++ rootLabel tree) mapM_ (printTree $ indent + 2) (subForest tree) treeHelper :: FilePath -> IO [Tree FilePath] treeHelper path = let filter' = filter (`notElem` [".", ".."]) in do contents <- getDirectoryContents path trees <- mapM (tree path) (filter' contents) return trees tree :: FilePath -> FilePath -> IO (Tree FilePath) tree parent path = let fullPath = (parent ++ "/" ++ path) in do isDirectory <- doesDirectoryExist fullPath case isDirectory of False -> return $ Node path  True -> treeHelper fullPath >>= (return . Node (path ++ "/"))
If you run it, it might print something like this:
./ dist/ build/ autogen/ cabal_macros.h Paths_Tree.hs tree/ tree tree-tmp/ Main.hi Main.o package.conf.inplace setup-config Setup.lhs tree.cabal Tree.hs
I think this is pretty nifty. It's a toy program, so I purposefully left out stuff like error checking and symlink handling and etc. How would you improve this program? Am I duplicating functionality available in a library? Are there places where the code could be tighter? Is my Haskell style not up to snuff?