Project 1b

Due Date: Mon 2 April
Individual Project

Programming Part

Refactor the previous project along the lines of the functor-based org chart example. Use HUnit for unit testing. The specific steps are as follows:
  1. Define a suitable flat (nonrecursive) algebraic data type ShapeData for representing the attributes of the different kinds of shapes (but not their children). This time, use Float instead of Int for all coordinates and sizes.
  2. Define the type Shape based on rose trees and ShapeData.
  3. Create a factory function for each kind of shape, e.g., mkRectangle.
  4. Create the test fixtures (sample shape trees).
  5. Define the bounding box and size functions nonrecursively using the cata function shown below. The functions defined in Data.Foldable are not powerful enough for this purpose. See below for more details and follow the example for depth.
  6. Define a new function scale :: Float -> Shape -> Shape using Data.Functor.fmap. For the purpose of this project, the scale function scales all coordinates and sizes up or down by the provided factor.
  7. Incorporate the test suite from the previous project and add tests for scale.
Again, no visual drawing of the shapes is required. 

Written Part

Address the following questions in a brief plain-text or Markdown document of about 200-300 words.
  • How do you compare this approach to the one from the previous project in terms of these quality attributes?
    • modifiability
    • integrability
    • portability
    • performance
    • reliability
    • ease of creation
    • reusability
    • any other quality you can think of
  • Data.Foldable.foldl requires a monoid. Research this and very briefly describe the concept in lay terms. What type plays the role of the monoid in the case of
    • size
    • bounding box
  • Briefly describe any other aspects of this project experience you found noteworthy.

Catamorphism for Rose Trees

Consider the type of Data.Foldable.foldr where t = Tree.

foldr :: (a -> b -> b) -> b -> Tree a -> b

Instead, we need this proper catamorphism factory function for rose trees. (The references below discuss how to generalize this for recursive types over arbitrary functors!)

cata :: (a -> [b] -> b) -> Tree a -> b
cata g (Node x ys) = g x (map (cata g) ys)

Note the similarity in types. The key difference is that cata's processing function g takes a list of items as its second argument. These are the results obtained from recursively applying g to all children of the node!

Here is a processing function for computing the depth of a shape tree.

gDepth :: ShapeData ->    [Int] -> Int
gDepth    (Ellipse _ _)   []     = 1
gDepth    (Rectangle _ _) []     = 1
gDepth    (Location _ _)  [s]    = 1 + s
gDepth    Group           ss     = 1 + Prelude.maximum ss