Skip to content

Instantly share code, notes, and snippets.

@varnie
Last active August 29, 2015 14:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save varnie/6eccdf5141a1b590d80b to your computer and use it in GitHub Desktop.
Save varnie/6eccdf5141a1b590d80b to your computer and use it in GitHub Desktop.
mport System.Environment
import System.Directory
import Control.Monad
import Data.List
import Control.Applicative
import qualified Data.ByteString.Char8 as L
import qualified Data.ByteString as B
import System.IO
import System.IO.Error
main = do
args <- getArgs
case args of
--1st way
--[ext] -> --do
--curDir <- getCurrentDirectory
--process ext curDir >>= print
--2nd way
[ext] -> getCurrentDirectory >>= process ext >>= print
_ -> putStrLn usage
`catchIOError` handler
handler :: IOError -> IO ()
handler e
-- | isDoesNotExistError e = putStrLn "The file doesn't exist!"
-- | isIllegalOperation e = putStrLn "Illegal operation"
-- | isPermissionError e = putStrLn "Permissions error"
-- | isUserError e = putStrLn "User error"
-- | isAlreadyInUseError e = putStrLn "Already in use"
| otherwise = ioError e
process::String->FilePath->IO Int
process ext dir = do
--1st way
--fnames <- getDirectoryContents dir
--let filteredNames = filter (\x -> not $ x `elem` [".", ".."]) fnames
--2nd way
--filteredNames <- getDirectoryContents dir >>= filterM (\x -> return . not $ x `elem` [".", ".."])
--3rd way
let filterOut = getDirectoryContents dir >>= filterM (\x -> return $ x `notElem` [".", ".."])
filteredNames <- filterOut
--print $ "dir: " ++ dir
--print "files: " >> print filteredNames
let filesLengths = map (\fname -> do
let curPath = fpath dir fname
isFile <- doesFileExist curPath
isDir <- doesDirectoryExist curPath
if isFile
then if ext `isSuffixOf` fname
then processFileStrict curPath
else return 0
else if isDir
then process ext curPath
else return 0
) filteredNames
--1st way
fmap sum $ sequence filesLengths
--2nd way
--fmap sum ( forM filesLengths $ id )
--3rd way
--foldM (fmap . (+)) 0 filesLengths
--4th way
--foldl (\x y -> pure (+) <*> x <*> y) (pure 0) filesLengths
where
fpath dir fname = dir ++ "/" ++ fname
processFile::String->IO Int
processFile f = readFile f >>= return . length . lines
processFileStrict::String->IO Int
processFileStrict f = withFile f ReadMode $ \hdd -> do
text <- B.hGetContents hdd
return $ length . L.lines $ text
usage :: String
usage = "usage: lines_count [extension]"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment