import System.Environment (getArgs)
import Data.List

interactWith function inputFile outputFile = do
  input <- readFile inputFile
  writeFile outputFile (function input)

main = mainWith myFunction
  where mainWith function = do
          args <- getArgs
          case args of
            [input,output] -> interactWith function input output
            _ -> putStrLn "error: exactly two arguments needed"

        myFunction = transposeFile

splitLines [] = []
splitLines cs =
    let (pre, suf) = break isLineTerminator cs
    in  pre : case suf of 
                ('\r':'\n':rest) -> splitLines rest
                ('\r':rest)      -> splitLines rest
                ('\n':rest)      -> splitLines rest
                _                -> []

isLineTerminator c = c == '\r' || c == '\n'

transposeFile :: String -> String
transposeFile input = unlines $ transposeLines $ splitLines input
-- there is alreadsy a function in the Prelude to transpose lists
-- transposeFile input = unlines $ transpose $ splitLines input

transposeLines :: [String] -> [String]
transposeLines xs = if null heads 
                    then []
                    else heads : transposeLines tails
                         where heads = concat $ map safeFirst xs
                               tails = map safeRest xs

safeFirst :: [a] -> [a]
safeFirst []     = []
safeFirst (x:xs) = [x]

safeRest :: [a] -> [a]
safeRest []     = []
safeRest (x:[]) = []
safeRest (_:xs) = xs

