Well, I thought that I’d have the time to do all the extra credit excercises for Haskell Day Two. But as it turned out I got stuck on the justify some text question. I guess this sort of question gets easier, but I couldn’t get the structure I wanted — a list of two tuples of
- Number of spaces to pad by
- List of words
I did, however, manage to finish the other two questions so here they are.
Break a long string into individual lines at proper word boundaries
Add line numbers to the previous excercise
Like I said, I got a little stuck doing the right and centre justification question, however, you’ll notice that my solution does right pad the left justified text. The linenums function really put a big smile on my face, its great being able to compose a big chain of functions, it felt like piping in the UNIX shell.
module Main where
tokenize str = words str
-- given a list of words returns a line's worth of them
lineify :: Int -> Int -> [[Char]] -> [Char]
lineify tw colCount words
| words ==  = 
| colCount < length headword = getSpaces++"\n"++(lineify tw tw words) -- left justify
| otherwise = headword++" "++(lineify tw decrementCc (tail words))
headword = head words
decrementCc = colCount - 1 - (length headword)
getSpaces = take colCount (repeat ' ')
-- add line numbers
linenums tw text =
. map (\(x,y) -> show x ++ " " ++ y)
. zip [1..]
. lineify tw tw $ tokenize text
As you can see tokenize is just a wrapper for the built in words function. Lineify recursively builds a padded left justified string from the words input. I should put in an error check for single words that are greater than the text width were I to use this code in production. linenums, like I said is the funnest function, it chains the lineified tokenized original text, splitting it into lines with the lines function, zipping it with the lazily evaluated infinite list of Integers, mapping each of those tuples into a string made up of the integer cast into a string and the line as a string, then finally rejoining the string with unlines. Clear? Good. Let’s run it.
As I head into the final day of the final language of my seven in seven weeks, I feel like I have started to get more of a handle on Haskell. It is a really cute language to play with, being so purely functional. Despite my occasional misunderstandings of its syntax, I am still rather enjoying Haskell.