Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- getFilePathBreadtFirst :: FilePath -> IO [FilePath]
- getFilePathBreadtFirst fp = do
- fileinfo <- getInfo fp
- res :: [FilePath] <- if isReadableDirectory fileinfo
- then do
- children <- getChildren fp
- lower <- mapM getFilePathBreadtFirst children
- return (children ++ concat lower)
- else return [fp] -- should only return the files?
- return res
- getChildren :: FilePath -> IO [FilePath]
- getChildren path = do
- names <- getUsefulContents path
- let namesfull = map (path </>) names
- return namesfull
- testBF fn = do -- crashes for /home/frank, does not go to swap
- fps <- getFilePathBreadtFirst fn
- putStrLn $ unlines fps
- import Control.Monad
- import Control.Monad.Trans
- import Control.Monad.Trans.Maybe
- import Control.Monad.State.Lazy
- import Control.Pipe
- import Data.Sequence
- import System.FilePath.Posix
- import System.Directory
- loop :: (Monad m) => MaybeT m a -> m ()
- loop = liftM (maybe () id) . runMaybeT . forever
- quit :: (Monad m) => MaybeT m a
- quit = mzero
- getUsefulContents :: FilePath -> IO [FilePath]
- getUsefulContents path
- = fmap (filter (`notElem` [".", ".."])) $ getDirectoryContents path
- permissible :: FilePath -> IO Bool
- permissible file
- = fmap (p -> readable p && searchable p) $ getPermissions file
- traverseTree :: FilePath -> Producer FilePath IO ()
- traverseTree path = (`evalStateT` empty) $ loop $ do
- -- All code past this point uses the following monad transformer stack:
- -- MaybeT (StateT (Seq FilePath) (Producer FilePath IO)) ()
- let liftState = lift
- liftPipe = lift . lift
- liftIO = lift . lift . lift
- liftState $ modify (|> path)
- forever $ do
- x <- liftState $ gets viewl
- case x of
- EmptyL -> quit
- file :< s -> do
- liftState $ put s
- liftPipe $ yield file
- p <- liftIO $ doesDirectoryExist file
- when p $ do
- names <- liftIO $ getUsefulContents file
- -- allowedNames <- filterM permissible names
- let namesfull = map (path </>) names
- liftState $ forM_ namesfull $ name -> modify (|> name)
- printer :: (Show a) => Consumer a IO r
- printer = forever $ do
- a <- await
- lift $ print a
- >>> runPipe $ printer <+< traverseTree path
- <Prints file names as it traverses the tree>
- -- Demand only 'n' elements
- take' :: (Monad m) => Int -> Pipe a a m ()
- take' n = replicateM_ n $ do
- a <- await
- yield a
- >> runPipe $ printer <+< take' 3 <+< traverseTree path
- <Prints only three files>
- traverseTree :: FilePath -> Producer FilePath IO ()
- -- ^ traverse a tree in breadth first fashion using an external doBF function
- traverseTree path = (`evalStateT` empty) $ loop $ do
- -- All code past this point uses the following monad transformer stack:
- -- MaybeT (StateT (Seq FilePath) (Producer FilePath IO)) ()
- let liftState = lift
- liftPipe = lift . lift
- liftIO = lift . lift . lift
- liftState $ modify (|> path)
- forever $ do
- x <- liftState $ gets viewl
- case x of
- EmptyL -> quit
- file :< s -> do
- (yieldval, nextInputs) <- liftIO $ doBF file
- liftState $ put s
- liftPipe $ yield yieldval
- liftState $ forM_ nextInputs $ name -> modify (|> name)
- doBF :: FilePath -> IO (FilePath, [FilePath])
- doBF file = do
- finfo <- getInfo file
- let p = isReadableDirectoryNotLink finfo
- namesRes <- if p then do
- names :: [String] <- liftIO $ getUsefulContents file
- let namesSorted = sort names
- let namesfull = map (file </>) namesSorted
- return namesfull
- else return []
- return (file, namesRes)
Add Comment
Please, Sign In to add comment