I am trying to write a simple version of the unix tail utility in haskell to improve my understanding of monads. Here is what I have now. I am pretty sure that this is not quite "Haskell enough" yet. Can you please help me improve my code?

import System.Environment
import System.Exit

main = getArgs >>= (parse' (10, [])) >>= \ (n_lines, ss) ->
putStr $concatMap (tailFile n_lines) ss tailFile :: Int -> (FilePath, String) -> String tailFile n_lines (f, c) = "==> " ++ f ++ " <==\n" ++ (unlines.reverse.(take n_lines).reverse.lines) c parse' :: (Int, [(FilePath, String)]) -> [String] -> IO (Int, [(FilePath, String)]) parse' _ ("-h":_) = putStrLn "usage: " >> exit parse' _ ("-v":_) = putStrLn "version: 0.1" >> exit parse' (_, ss) ("-n":num:f) = parse' (read num, ss) f parse' (n, ss) (f:fs) = do contents <- readFile f parse' (n, ss ++ [(f,contents)]) fs parse' (x, ss) [] = return (x, ss) exit = exitWith ExitSuccess die = exitWith (ExitFailure 1)  ## 1 Answer My first approach is to map the arguments to a list of IO actions and then execute them: import Control.Monad import System.Environment lastLines :: Int -> String -> [String] lastLines n = reverse.take n.reverse.lines printLines :: [String] -> IO () printLines = flip forM_$ putStrLn

readLastLines :: Int -> FilePath -> IO [String]
readLastLines n f = readFile f >>= return . (++) ["==>" ++ f ++ "<=="] . lastLines n

argsToActions :: [String] -> [IO ()]
argsToActions ("-h":_) = [print "Usage"]
argsToActions ("-v":_) = [print "V 1.0"]