Last active
December 11, 2017 01:23
-
-
Save coodoo/3be2e687b37e1ae4a10b8ca0a28616a8 to your computer and use it in GitHub Desktop.
Revised according to code review on reddit: https://www.reddit.com/r/haskell/comments/7imf2x/iostate_monad_code_sample_for_review/?st=jazawqt9&sh=73b39155
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
module Main where | |
import Control.Monad.State | |
import System.Directory | |
import System.Exit | |
import System.FilePath | |
import Data.Time | |
data File = File | |
{ name :: FilePath | |
, date :: UTCTime | |
, size :: Integer | |
, content :: String | |
} deriving (Show) | |
data Dir = Dir | |
{ dirName :: FilePath | |
, dirDate :: UTCTime | |
, dirContent :: [FilePath] | |
} deriving (Show) | |
data Order = Desc | Asc | |
deriving (Eq) | |
k :: FilePath -> IO ([Dir], [File]) | |
k root = do | |
isDir <- doesDirectoryExist root | |
unless isDir $ die "not a dir" | |
execStateT (list root) ([],[]) | |
partitionM :: Monad m => (a -> m Bool) -> [a] -> m ([a], [a]) | |
partitionM _ [] = return ([], []) | |
partitionM f (x:xs) = do | |
res <- f x | |
(as, bs) <- partitionM f xs | |
return ([x | res] ++ as, [x | not res] ++ bs) | |
list :: FilePath -> StateT ([Dir], [File]) IO () | |
list path = do | |
dir <- | |
liftIO $ | |
do | |
children <- listDirectory path | |
dt <- getModificationTime path | |
return Dir {dirName = path, dirContent = children, dirDate = dt} | |
modify (\(ds, fs) -> (dir : ds, fs)) | |
let | |
filteredFiles = filter (not . (`elem` [".DS_Store", ".config", ".stack"])) $ dirContent dir | |
fullPaths = map (path </>) filteredFiles | |
(dirs, files) <- liftIO $ partitionM doesDirectoryExist fullPaths | |
forM_ dirs list | |
forM_ files $ \f -> do | |
file <- liftIO $ do | |
s <- getFileSize f | |
dt <- getModificationTime f | |
c <- readFile f | |
return File {name = f, date = dt, size = s, content = c} | |
modify (\(ds, fs) -> (ds, file:fs)) | |
pretty :: Show a => [a] -> Order -> String -> IO () | |
pretty src rev prefix = do | |
putStrLn $ "\n" ++ prefix ++ "\n" | |
if rev == Desc | |
then mapM_ print $ reverse src | |
else mapM_ print src | |
main :: IO () | |
main = do | |
(d, f) <- k "aaa" | |
pretty d Desc "DIR:" | |
pretty f Asc "FILE:" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment