# Probably unneeded returns

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 =

main = do
args <- getArgs
argc <- return $length args destination <- return$ last args
concatFiles destination $take (argc-1) args  - ## 1 Answer For your argc <- return$ length args , the reason the compiler is telling you to use the return is because in do notation, monadic binding lines must be the form:

binding <- value wrapped in whatever monad you're using


So length args just returns an Int, but Haskell wants an IO Int. By doing return $length args, you lift the value returned by length args into the IO monad. You are correct in smelling something funny here. Haskell provides a much cleaner way of assigning non-monadic values to be used inside of do notation with the let keyword. You can replace those two lines with: let argc = length args destination = last args  Note that bindings must have the same indentation level within a let assignment block. But really, there is more to improve! In Haskell, the four most common list partitions are: 1. First element (head) 2. Last element (last) 3. Everything but the first (tail) 4. 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.

-
If you're going to get fancy by using >>=, you may as well get rid of the lambda as well! main = getArgs >>= concatFiles <\$> last <*> init. –  amalloy Mar 20 '14 at 6:57
@amalloy exactly what I was thinking –  recursion.ninja Apr 27 '14 at 19:46