import System.Directory (getDirectoryContents, doesDirectoryExist)
data Tree a = Directory a [Tree a] | File a  deriving (Show)
makeTheTree :: FilePath -> IO (Tree FilePath)
makeTheTree path = do
    isDirecotry <- doesDirectoryExist path
    if not isDirecotry then
        return $ File path
    else do
        content <- getDirectoryContents path
        tree <- mapM makeTheTree (processFiles content)
        return $ Directory path tree
    where
        processFiles :: [FilePath] -> [FilePath]
        processFiles files = map ((path ++) . ("/" ++)) $ discardDots files
discardDots :: [FilePath] -> [FilePath]
discardDots = filter (\file -> file /= "." && file /= "..")
traverseBF :: Tree a -> [a]
traverseBF tree = tbf [tree] where
    tbf [] = []
    tbf xs = concatMap files xs ++ tbf (concatMap directories xs)
    
    files :: Tree a -> [a]
    files (File a) = [a]
    files (Directory _ _) = []
    
    directories :: Tree a -> [Tree a]
    directories (File  _) = []
    directories (Directory _ ys) = ys
main = (traverseBF <$> makeTheTree "/usr/local") >>= mapM_ (print . length . filter (=='/'))