1 module Main(main) where
  2 
  3 import qualified Data.ByteString as BS
  4 import qualified IO
  5 import System(getArgs)
  6 import Monad(mapM_)
  7 import qualified Scaffolding
  8 
  9 
 10 -- Top level mergesort function; this way the 'length' operator is
 11 -- only invoked once on the original list.
 12 mergesort l =
 13     mergesort_ l llen
 14     where llen = length l
 15 
 16 -- Please note that the length of the list to be sorted is now passed
 17 -- in as a parameter.
 18 mergesort_ l llen =
 19     if llen <= 1 then l -- The list is already sorted.
 20     else -- Split the list into two halves and sort these.
 21         merge (mergesort_ ls left_len) (mergesort_ rs right_len)
 22         where (ls, rs) = splitAt left_len l
 23               left_len = llen `div` 2
 24               -- Takes care of lists with odd number of elements.
 25               right_len = llen - left_len
 26 
 27 merge ls [] = ls
 28 merge [] rs = rs
 29 merge (l:ls) (r:rs) =
 30     if l <= r then l:(merge ls (r:rs)) else r:(merge (l:ls) rs)
 31 
 32 -- The main method, handles command line arguments, input and output.
 33 main = do
 34     args <- getArgs
 35     fileh <- case head args of
 36                 -- The text to be sorted is to be read from stdin.
 37                 "-" -> do return (Just IO.stdin)
 38                 -- The text to be sorted is to be read from the file
 39                 -- specified.
 40                 "-f" -> do Scaffolding.openFile (head (tail args))
 41                 -- Just sort the command line parameters.
 42                 _ -> do let sorted_args = mergesort args
 43                         IO.putStrLn ("mergesort(" ++ show args ++
 44                                      ") = " ++ show sorted_args)
 45                         return Nothing
 46     case fileh of
 47         -- Read text from file handle, sort it and print to stdout.
 48         Just fileh -> do text_to_sort <- Scaffolding.readLines fileh []
 49                          mapM_ BS.putStrLn (mergesort text_to_sort)
 50         -- We failed to open the file specified (if any).
 51         Nothing -> do return ()