Real World Haskell, Exercise 4, p. 84:

Write a program that transposes the text in a file. For instance, it should convert “hello\nworld\n” to “hw\neo\nlr\nll\nod\n”.

cc :: String -> String -> String
cc x y = x ++ y ++ "\n"

transposeSingle :: String -> String
transposeSingle [] = []
transposeSingle (x:xs) = x : '\n' : (transposeSingle xs)

-- the accumulator string and the next line
transposeDouble :: String -> String -> String
transposeDouble x y = concat (zipWith (cc) (lines x) (lines (transposeSingle y)))

transposeEven :: [String] -> String
transposeEven [] = []
transposeEven [x] = (transposeSingle x) 
transposeEven (x:xs) = foldl (transposeDouble) (transposeSingle x) xs

transpose :: String -> String
transpose s = transposeEven (pad (maxLength s) (lines s))

-- pad each line with spaces to maximum length
maxLength :: String -> Int
maxLength s = maximum (map length (lines s))

pad :: Int -> [String] -> [String]
pad _ [] = []
pad n (x:xs) = (padOneLine (n - (length x)) x) : (pad n xs)

padOneLine :: Int -> String -> String
padOneLine n s = if n > 0
                 then padOneLine (n-1) (s ++ ".")
                 else s

The exercise wasn’t clear on what you should do when not all lines were the same size, so I padded them out with periods.

This took way longer to implement than it should have, and I had to use several functions from later parts of the book. I certainly could have implemented this faster in Java or, to pick a language I haven’t been using day in and day out for 14 years, Python. Doubtless an experienced Haskell programmer could come up with a simpler implementation.

On the positive side, the interactive ghci shell was a big help in debugging this, and by their very nature Haskell’s pure functions are very amenable to testing and debugging in isolation. However, I still have to learn how to do real test driven development in Haskell. (One thing I proved to myself a couple of jobs ago was that TDD matters a lot more than what language you code in. I figured this out after I realized I could write correct Python code faster than the professional Python programmers we had hired because I was using TDD and they weren’t. This despite the fact that I knew next to no Python and they had years of experience in the language. Of course, an experienced Python programmer who did use test-driven development could still wipe the floor with me. )

2 Responses to “transpose”

  1. Michael Day Says:

    You could try QuickCheck.

  2. PW Says:

    Isn’ the answer just

    import Data.List
    transposeWords :: String -> String
    transposeWords s = foldr (\s -> \e -> s ++ “\n” ++ e ) “” (transpose (lines s))

Leave a Reply