Does this make my code look big?

July 27, 2009

Real World Haskell Chapter 5 – Haskell

Filed under: Chapter 5,Code,Exercise,Haskell — Barry Allison @ 10:02 pm
Tags:

There are only 2 exercises in Chapter 5 which both live in the Prettify.hs file.
I’ve uploaded all of the files I created developing the JSON library for completeness and to be able to actually compile and use it.
Chapter 5 JSON library exercise solutions:

The files I wrote to create the libraries cabal package:

All in all I found this chapter a bit confusing which I think is because the ideas behind it are obviously based on the built in Haskell pretty printing library which isn’t introduces until the end of the chapter. There was no real clear explanation of the structure and purpose of the different parts of the library which made reading and following some of the ideas very dry. Plus not much clarity about the placing of some of the definitions, stubs and functions.

Having said that the overall structure for writing the exercise solutions are given in the pretty and compact functions so both exercises were just a matter of adapting them to the job at hand.

Exercise 1

Keep a note of the current column (in the same way pretty does) and whenever a Line is encountered append spaces at the end of the current line to pad it out to the required width. The rest of the tree structure of the Document is maintained ‘as is’.

fill :: Int -> Doc -> Doc
fill width d = scanLines 0 [d]
    where scanLines col (d:ds) =
              case d of
                Empty        -> Empty  scanLines col ds
                Char c       -> d  scanLines (col + 1) ds
                Text s       -> d  scanLines (col + length s) ds
                Line         -> (padLine col  Line)  scanLines 0 ds
                a `Concat` b -> scanLines col (a:b:ds)
                a `Union` b  -> scanLines col (a:ds) `Union`  scanLines col (b:ds)
          scanLines _ _ = Empty
          padLine pos = text $ replicate (width - pos) ' '

Exercise 2

This works in the same way that fill does except the current line’s nesting position is maintained rather than the current item’s character position in the current line.
When an open brace or bracket is found the nesting is increased and when closing braces or brackets are found the nesting is decreased. After a new Line spaces are added to the beginning of the line according to the current nesting value. In the renderJValue function braces are implemented using only Char Doc values
- initially I also checked inside Text Doc values as well but realized that it isn’t necessary.

nest :: Int -> Doc -> Doc
nest indent d = scanLines 0 [d]
    where scanLines col (d:ds) =
              case d of
                Empty        -> d  scanLines col ds
                Char c       -> d  scanLines (col + offset c) ds
                Text s       -> d  scanLines col ds
                Line         -> d  indentLine col  scanLines col ds
                a `Concat` b -> scanLines col (a:b:ds)
                a `Union` b  -> scanLines col (a:ds) `Union`  scanLines col (b:ds)
          scanLines _ _        = Empty

          indentLine pos    = text $ replicate pos ' '
          offset c | c `elem` "{[" = indent
                   | c `elem` "}]" = negate indent
                   | otherwise     = 0

Leave a Comment »

No comments yet.

RSS feed for comments on this post. TrackBack URI

Leave a Reply

Please log in using one of these methods to post your comment:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Connecting to %s

Theme: Rubric. Blog at WordPress.com.

Follow

Get every new post delivered to your Inbox.