Last active
August 29, 2015 14:02
-
-
Save bor0/da511c3891a875ceeb71 to your computer and use it in GitHub Desktop.
CountLinesOfCode
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
import System.Directory | |
import Control.Monad (filterM, mapM, liftM) | |
import System.FilePath ((</>)) | |
getDirsRec :: FilePath -> IO [FilePath] | |
getDirsRec d = do | |
dirContents <- getDirectoryContents d | |
let dirContents' = [ d </> x | x <- dirContents, x /= ".", x /= ".." ] | |
dirs' <- mapM dirRec dirContents' | |
return (concat dirs' ++ [d]) | |
where | |
dirRec n = do | |
isDir <- doesDirectoryExist n | |
if isDir then getDirsRec n | |
else return [] | |
getFiles :: FilePath -> IO [FilePath] | |
getFiles d = do | |
dirContents <- getDirectoryContents d | |
filterM doesFileExist (map (d </>) dirContents) | |
getLOC :: FilePath -> IO Int | |
getLOC f = (length . lines) `fmap` readFile f | |
main = liftM sum (getDirsRec "." >>= mapM getFiles >>= mapM getLOC . concat) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
<frerich> boR0: I think a good improvement would be to not implement the directory walking yourself. Instead, use System.FilePath.Find.fold
<frerich> bor0: Something like 'find always (acc f -> acc + linesInFile f) "."'
<BoR0> frerich, I thought such function existed, but I was gonna play around with IO and experiment stuff
<frerich> bor0: Ah, well - if you are more looking for 'coding style' commentary. The first few things which came to my head when reading your paste were 1. "Why use filterM instead of plain filter?", "dirs ++ ds" will be somewhat inefficient if 'dirs' is large and "foldingFunction" is not a terribly nice name for a function.
<frerich> Oh, I forgot to insert 2. and 3. I guess :)
<BoR0> ok, about 1, how can I use filter instead of filterM for a IO function like doesFileExist?
<frerich> bor0: You can't. That's just the first thought which crossed my mind. :)
<BoR0> ah, okay
<tdammers> you can, sort of, but you'll just end up rewriting filterM with other ...M functions
<frerich> bor0: I think it would be nice to separate this problem into three tasks: 1. Get a list of all files beneath some directory. 2. Getting the lines of text in a file. Then you could do something like "sum . map linesInFile . getFilesBenath $ someDir"
<frerich> bor0: I.e. not mangle it all into once.
<frerich> bor0: ...except that you'd use fmap or instead of 'map' :)
<BoR0> frerich, that's a good suggestion, I'll probably rewrite it that way