Aspiring haskeller here. I wrote a script to take a filepath argument, read the contents where each line will be a relative filepath, and count the lines of each filepath and print it to the command line. It relies on System.Directory.Internal.Prelude.for_
to loop through the file's contents and print each length to the console.
- Question 1: How would you remove the
for
loop? - Question 2: If
getFileLength
had a signature of `FilePath -> IO(Maybe(Int)), how would you refactor the program? (Does this question make sense?)
import System.Environment
import System.Directory
import System.IO
import Data.Char
import System.Directory.Internal.Prelude (for_)
main = do
(configPath:_) <- getArgs
configContents <- readFile configPath
let filePaths = lines configContents
for_ filePaths (\path -> do getFileLength path)
getFileLength :: FilePath -> IO()
getFileLength path = do
contents <- readFile path
putStrLn $ "- [ ] " path " (" show (length (lines contents)) ")"
Thank you
CodePudding user response:
You can use mapM_ :: (Foldable t, Monad m) => (a -> m b) -> t a -> m ()
or traverse_ :: (Foldable t, Applicative f) => (a -> f b) -> t a -> f ()
:
main :: IO ()
main = do
(configPath:_) <- getArgs
configContents <- readFile configPath
mapM_ getFileLength (lines configContents)
or:
import Data.Foldable(traverse_)
main :: IO ()
main = do
(configPath:_) <- getArgs
configContents <- readFile configPath
traverse_ getFileLength (lines configContents)