Due Date: Mon 2 April
- 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.
- Define the type Shape based on rose trees and ShapeData.
- Create a factory function for each kind of shape, e.g., mkRectangle.
- Create the test fixtures (sample shape trees).
- 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.
- 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.
- Incorporate the test suite from the previous project and add tests for scale.
Again, no visual drawing of the shapes is required.
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?
- ease of creation
- 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
- 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