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

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.