module CountEntries ( countEntries0
, countEntries1
, countEntries2
, countEntries3
) where
import Control.Monad (filterM, forM, forM_, when)
import Control.Monad.Trans (liftIO)
import Control.Monad.Trans.Writer (WriterT, execWriterT, tell)
import System.Directory (doesDirectoryExist, listDirectory)
import System.FilePath ((</>))
countEntries0 :: FilePath -> IO [(FilePath, Int)]
countEntries0 :: FilePath -> IO [(FilePath, Int)]
countEntries0 FilePath
path = do
[FilePath]
contents <- FilePath -> IO [FilePath]
listDirectory FilePath
path
[[(FilePath, Int)]]
rest <- [FilePath]
-> (FilePath -> IO [(FilePath, Int)]) -> IO [[(FilePath, Int)]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
t a -> (a -> m b) -> m (t b)
forM [FilePath]
contents ((FilePath -> IO [(FilePath, Int)]) -> IO [[(FilePath, Int)]])
-> (FilePath -> IO [(FilePath, Int)]) -> IO [[(FilePath, Int)]]
forall a b. (a -> b) -> a -> b
$ \FilePath
name -> do
let newName :: FilePath
newName = FilePath
path FilePath -> FilePath -> FilePath
</> FilePath
name
Bool
isDir <- FilePath -> IO Bool
doesDirectoryExist FilePath
newName
if Bool
isDir
then FilePath -> IO [(FilePath, Int)]
countEntries0 FilePath
newName
else [(FilePath, Int)] -> IO [(FilePath, Int)]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return []
[(FilePath, Int)] -> IO [(FilePath, Int)]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(FilePath, Int)] -> IO [(FilePath, Int)])
-> [(FilePath, Int)] -> IO [(FilePath, Int)]
forall a b. (a -> b) -> a -> b
$ (FilePath
path, [FilePath] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FilePath]
contents) (FilePath, Int) -> [(FilePath, Int)] -> [(FilePath, Int)]
forall a. a -> [a] -> [a]
: [[(FilePath, Int)]] -> [(FilePath, Int)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat [[(FilePath, Int)]]
rest
countEntries1 :: FilePath -> IO [(FilePath, Int)]
countEntries1 :: FilePath -> IO [(FilePath, Int)]
countEntries1 FilePath
p =
if Bool -> Bool
not (FilePath -> Bool
forall a. [a] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
null FilePath
p)
then
FilePath -> IO [FilePath]
listDirectory FilePath
p
IO [FilePath]
-> ([FilePath] -> IO [(FilePath, Int)]) -> IO [(FilePath, Int)]
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \[FilePath]
ps -> (FilePath -> IO Bool) -> [FilePath] -> IO [FilePath]
forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM (\FilePath
n -> FilePath -> IO Bool
doesDirectoryExist (FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
n)) [FilePath]
ps
IO [FilePath]
-> ([FilePath] -> IO [[(FilePath, Int)]]) -> IO [[(FilePath, Int)]]
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (FilePath -> IO [(FilePath, Int)])
-> [FilePath] -> IO [[(FilePath, Int)]]
forall (t :: * -> *) (m :: * -> *) a b.
(Traversable t, Monad m) =>
(a -> m b) -> t a -> m (t b)
forall (m :: * -> *) a b. Monad m => (a -> m b) -> [a] -> m [b]
mapM (\FilePath
n -> FilePath -> IO [(FilePath, Int)]
countEntries1 (FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
n))
IO [[(FilePath, Int)]]
-> ([[(FilePath, Int)]] -> IO [(FilePath, Int)])
-> IO [(FilePath, Int)]
forall a b. IO a -> (a -> IO b) -> IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (\[(FilePath, Int)]
ces -> [(FilePath, Int)] -> IO [(FilePath, Int)]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return ([(FilePath, Int)] -> IO [(FilePath, Int)])
-> [(FilePath, Int)] -> IO [(FilePath, Int)]
forall a b. (a -> b) -> a -> b
$ (FilePath
p, [FilePath] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FilePath]
ps) (FilePath, Int) -> [(FilePath, Int)] -> [(FilePath, Int)]
forall a. a -> [a] -> [a]
: [(FilePath, Int)]
ces) ([(FilePath, Int)] -> IO [(FilePath, Int)])
-> ([[(FilePath, Int)]] -> [(FilePath, Int)])
-> [[(FilePath, Int)]]
-> IO [(FilePath, Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [[(FilePath, Int)]] -> [(FilePath, Int)]
forall (t :: * -> *) a. Foldable t => t [a] -> [a]
concat
else [(FilePath, Int)] -> IO [(FilePath, Int)]
forall a. a -> IO a
forall (m :: * -> *) a. Monad m => a -> m a
return []
countEntries2 :: FilePath -> IO [(FilePath, Int)]
countEntries2 :: FilePath -> IO [(FilePath, Int)]
countEntries2 = WriterT [(FilePath, Int)] IO () -> IO [(FilePath, Int)]
forall (m :: * -> *) w a. Monad m => WriterT w m a -> m w
execWriterT (WriterT [(FilePath, Int)] IO () -> IO [(FilePath, Int)])
-> (FilePath -> WriterT [(FilePath, Int)] IO ())
-> FilePath
-> IO [(FilePath, Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> WriterT [(FilePath, Int)] IO ()
countEntries2'
where
countEntries2' :: FilePath -> WriterT [(FilePath, Int)] IO ()
countEntries2' :: FilePath -> WriterT [(FilePath, Int)] IO ()
countEntries2' FilePath
path = do
[FilePath]
contents <- IO [FilePath] -> WriterT [(FilePath, Int)] IO [FilePath]
forall a. IO a -> WriterT [(FilePath, Int)] IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO [FilePath] -> WriterT [(FilePath, Int)] IO [FilePath])
-> (FilePath -> IO [FilePath])
-> FilePath
-> WriterT [(FilePath, Int)] IO [FilePath]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO [FilePath]
listDirectory (FilePath -> WriterT [(FilePath, Int)] IO [FilePath])
-> FilePath -> WriterT [(FilePath, Int)] IO [FilePath]
forall a b. (a -> b) -> a -> b
$ FilePath
path
[(FilePath, Int)] -> WriterT [(FilePath, Int)] IO ()
forall (m :: * -> *) w. Monad m => w -> WriterT w m ()
tell [(FilePath
path, [FilePath] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FilePath]
contents)]
[FilePath]
-> (FilePath -> WriterT [(FilePath, Int)] IO ())
-> WriterT [(FilePath, Int)] IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
t a -> (a -> m b) -> m ()
forM_ [FilePath]
contents ((FilePath -> WriterT [(FilePath, Int)] IO ())
-> WriterT [(FilePath, Int)] IO ())
-> (FilePath -> WriterT [(FilePath, Int)] IO ())
-> WriterT [(FilePath, Int)] IO ()
forall a b. (a -> b) -> a -> b
$ \FilePath
name -> do
let newName :: FilePath
newName = FilePath
path FilePath -> FilePath -> FilePath
</> FilePath
name
Bool
isDir <- IO Bool -> WriterT [(FilePath, Int)] IO Bool
forall a. IO a -> WriterT [(FilePath, Int)] IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (IO Bool -> WriterT [(FilePath, Int)] IO Bool)
-> (FilePath -> IO Bool)
-> FilePath
-> WriterT [(FilePath, Int)] IO Bool
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> IO Bool
doesDirectoryExist (FilePath -> WriterT [(FilePath, Int)] IO Bool)
-> FilePath -> WriterT [(FilePath, Int)] IO Bool
forall a b. (a -> b) -> a -> b
$ FilePath
newName
Bool
-> WriterT [(FilePath, Int)] IO ()
-> WriterT [(FilePath, Int)] IO ()
forall (f :: * -> *). Applicative f => Bool -> f () -> f ()
when Bool
isDir (WriterT [(FilePath, Int)] IO ()
-> WriterT [(FilePath, Int)] IO ())
-> WriterT [(FilePath, Int)] IO ()
-> WriterT [(FilePath, Int)] IO ()
forall a b. (a -> b) -> a -> b
$ FilePath -> WriterT [(FilePath, Int)] IO ()
countEntries2' FilePath
newName
countEntries3 :: FilePath -> IO [(FilePath, Int)]
countEntries3 :: FilePath -> IO [(FilePath, Int)]
countEntries3 = WriterT [(FilePath, Int)] IO () -> IO [(FilePath, Int)]
forall (m :: * -> *) w a. Monad m => WriterT w m a -> m w
execWriterT (WriterT [(FilePath, Int)] IO () -> IO [(FilePath, Int)])
-> (FilePath -> WriterT [(FilePath, Int)] IO ())
-> FilePath
-> IO [(FilePath, Int)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FilePath -> WriterT [(FilePath, Int)] IO ()
go
where
go :: FilePath -> WriterT [(FilePath, Int)] IO ()
go :: FilePath -> WriterT [(FilePath, Int)] IO ()
go FilePath
p =
IO [FilePath] -> WriterT [(FilePath, Int)] IO [FilePath]
forall a. IO a -> WriterT [(FilePath, Int)] IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO (FilePath -> IO [FilePath]
listDirectory FilePath
p)
WriterT [(FilePath, Int)] IO [FilePath]
-> ([FilePath] -> WriterT [(FilePath, Int)] IO ())
-> WriterT [(FilePath, Int)] IO ()
forall a b.
WriterT [(FilePath, Int)] IO a
-> (a -> WriterT [(FilePath, Int)] IO b)
-> WriterT [(FilePath, Int)] IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \[FilePath]
ps -> [(FilePath, Int)] -> WriterT [(FilePath, Int)] IO ()
forall (m :: * -> *) w. Monad m => w -> WriterT w m ()
tell [(FilePath
p, [FilePath] -> Int
forall a. [a] -> Int
forall (t :: * -> *) a. Foldable t => t a -> Int
length [FilePath]
ps)]
WriterT [(FilePath, Int)] IO ()
-> WriterT [(FilePath, Int)] IO [FilePath]
-> WriterT [(FilePath, Int)] IO [FilePath]
forall a b.
WriterT [(FilePath, Int)] IO a
-> WriterT [(FilePath, Int)] IO b -> WriterT [(FilePath, Int)] IO b
forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
>> IO [FilePath] -> WriterT [(FilePath, Int)] IO [FilePath]
forall a. IO a -> WriterT [(FilePath, Int)] IO a
forall (m :: * -> *) a. MonadIO m => IO a -> m a
liftIO ((FilePath -> IO Bool) -> [FilePath] -> IO [FilePath]
forall (m :: * -> *) a.
Applicative m =>
(a -> m Bool) -> [a] -> m [a]
filterM (\FilePath
n -> FilePath -> IO Bool
doesDirectoryExist (FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
n)) [FilePath]
ps)
WriterT [(FilePath, Int)] IO [FilePath]
-> ([FilePath] -> WriterT [(FilePath, Int)] IO ())
-> WriterT [(FilePath, Int)] IO ()
forall a b.
WriterT [(FilePath, Int)] IO a
-> (a -> WriterT [(FilePath, Int)] IO b)
-> WriterT [(FilePath, Int)] IO b
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= \[FilePath]
pss -> (FilePath -> WriterT [(FilePath, Int)] IO ())
-> [FilePath] -> WriterT [(FilePath, Int)] IO ()
forall (t :: * -> *) (m :: * -> *) a b.
(Foldable t, Monad m) =>
(a -> m b) -> t a -> m ()
mapM_ (\FilePath
n -> FilePath -> WriterT [(FilePath, Int)] IO ()
go (FilePath
p FilePath -> FilePath -> FilePath
</> FilePath
n)) [FilePath]
pss