-- | A simple library for representing shapes as type classes. module ShapeClass where import Numeric (sqrt) -- A type class for shapes that defines all the things shapes can do -- (again, like an interface in Java). class Shape s where area :: s -> Float perimeter :: s -> Float -- Adding our two initial shapes. type Radius = Float type Length = Float type Width = Float data Circle = Circle Radius deriving (Eq,Show) data Rectangle = Rectangle Length Width deriving (Eq,Show) instance Shape Circle where area (Circle r) = pi * r * r perimeter (Circle r) = 2 * pi * r instance Shape Rectangle where area (Rectangle l w) = l * w perimeter (Rectangle l w) = 2 * l + 2 * w -- And now adding a new shape is a modular extension. data Triangle = Triangle Length Width deriving (Eq,Show) instance Shape Triangle where area (Triangle l w) = (l * w) / 2 perimeter (Triangle l w) = l + w + sqrt (l * l + w * w) -- Add a combined shape data SideBySide a b = SideBySide a b deriving (Eq,Show) instance (Shape a, Shape b) => Shape (SideBySide a b) where area (SideBySide s1 s2) = area s1 + area s2 perimeter (SideBySide s1 s2) = undefined -- ??? -- To add a new function, we might do something like this. class Shape s => ExtShape s where diameter :: s -> Float instance ExtShape Circle where diameter (Circle r) = 2 * r instance ExtShape Rectangle where diameter (Rectangle l w) = sqrt (l*l + w*w) instance ExtShape Triangle where diameter (Triangle l) = l