5
\$\begingroup\$

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
import Control.Monad

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)
\$\endgroup\$

1 Answer 1

2
\$\begingroup\$

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"]
argsToActions ("-n":n:f:_) = [readLastLines (read n) f >>= printLines]
argsToActions (f:fs) = [readLastLines 10 f >>= printLines] ++ argsToActions fs
argsToActions [] = []

main :: IO ()
main = getArgs >>= sequence_ . argsToActions
\$\endgroup\$

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.