patternModerate
Probably unneeded returns
Viewed 0 times
probablyreturnsunneeded
Problem
This is my first "useful" Haskell program. It's invoked with filenames as arguments where the last filename is the destination to which the content of all other files will be concatenated. As far as I can tell it's working but I don't like the two returns in the main function and would like to know how I can get rid of the do in the concatFiles function.
import System.Environment (getArgs)
import System.IO (hClose, hPutStr, openFile, IOMode(WriteMode))
concatFiles :: FilePath -> [FilePath] -> IO ()
concatFiles destination files = do
writeHandle <- openFile destination WriteMode
mapM (writeToDestination writeHandle) files
hClose writeHandle
where
writeToDestination writeHandle file =
hPutStr writeHandle =<< readFile file
main = do
args <- getArgs
argc <- return $ length args
destination <- return $ last args
concatFiles destination $ take (argc-1) argsSolution
For your
argc
- Last element (
last)
- Everything but the first (
tail)
- Everything but the last (
init)
So with init we can eliminate the need for argc, changing your main to
main = do
args <- getArgs
let destination = last args
concatFiles destination $ init args
But really, the word destination is longer than the function call last args, and doesn't really add much clarity, so we can change that, too, removing the need for the let entirely!
main = do
args <- getArgs
concatFiles (last args) (init args)
And if you really wanted to become more intimately familiar with how do notations and monads in general work, we can actually remove the do notation and replace it with a >>= operator by doing
main = getArgs >>= \args -> concatFiles (last args) (init args)
So as a quick recap of what is happening here, we are calling getArgs, which returns a list of arguments wrapped in the IO monad. The >>= (bind) operator takes that IO value, extracts the value inside, and sends it into the function on the right side of the >>= operator, where it gets bound to the argument args`.Code Snippets
binding <- value wrapped in whatever monad you're usinglet argc = length args
destination = last argsmain = do
args <- getArgs
let destination = last args
concatFiles destination $ init argsmain = do
args <- getArgs
concatFiles (last args) (init args)main = getArgs >>= \args -> concatFiles (last args) (init args)Context
StackExchange Code Review Q#44799, answer score: 10
Revisions (0)
No revisions yet.