-- | A simple library for representing shapes as data types. module ShapeData where import Numeric (sqrt,showGFloat) -- Show a Float with exactly two decimal places. (Used in tests.) showF2 :: Float -> String showF2 x = showGFloat (Just 2) x "" -- Recall the shape library example from before. -- -- Initially: -- * two shapes (circles and rectangles) -- * two functions (area and perimeter) -- -- Adding a new function (diameter) was easy, -- but adding a new shape (Triangle) was hard. type Radius = Float type Length = Float type Width = Float data Shape = Circle Radius | Rectangle Length Width deriving (Eq,Show) -- | Smart constructor for building squares. square :: Length -> Shape square l = Rectangle l l -- | Compute the area of a shape. -- -- >>> area (square 2.0) -- 4.0 -- -- >>> showF2 $ area (Circle 1.0) -- "3.14" -- area :: Shape -> Float area (Circle r) = pi * r * r area (Rectangle l w) = l * w -- | Compute the perimiter of a shape. -- -- >>> perimeter (square 2.0) -- 8.0 -- -- >>> showF2 $ perimeter (Circle 1.0) -- "6.28" -- perimeter :: Shape -> Float perimeter (Circle r) = 2 * pi * r perimeter (Rectangle l w) = 2 * l + 2 * w -- ** Modular extensions -- | Compute the length of the longest line through a shape. -- -- >>> diameter (Circle 2.0) -- 4.0 -- -- >>> diameter (Rectangle 3.0 4.0) -- 5.0 -- diameter :: Shape -> Float diameter (Circle r) = 2 * r diameter (Rectangle l w) = sqrt (l*l + w*w) -- | Extended shape data type. data NewShape = OldShape Shape | Triangle Length Width deriving (Eq,Show) newArea :: NewShape -> Float newArea (OldShape s) = area s newArea (Triangle l w) = (l * w) / 2 newPerimeter :: NewShape -> Float newPerimeter (OldShape s) = perimeter s newPerimeter (Triangle l w) = l + w + sqrt (l * l + w * w)