content: -- | Simple library for 2D shapes. Shallow embedding.
  
  module Shape.Shallow
    (
    -- * Types
      Shape -- abstract
    -- * Constructor functions
    , empty, disc, square
    -- * Primitive combinators
    , transform, translate
    , union, intersect, invert
    -- * Run functions
    , inside
    ) where
  
  import Matrix
  
  newtype Shape = Shape (Point -> Bool)
  
  -- * Creation functions
  
  empty :: Shape
  empty = Shape \ _ -> False
  
  disc :: Shape
  disc = Shape \ p -> ptX p ^ 2 + ptY p ^ 2 <= 1
  
  square :: Shape
  square = Shape \ p -> abs (ptX p) <= 1 && abs (ptY p) <= 1
  
  -- * Primitive combinators
  
  -- | Transform a shape with a matrix.
  transform :: Matrix -> Shape -> Shape
  transform m sh = Shape \ p -> (inv_m `mul` p) `inside` sh
    where
      inv_m = inv m  -- the point is transformed with the inverse matrix
  
  -- To represent translations as matrix transformations we would need
  -- to add another dimension to the matrices (excercise).
  translate :: Vec -> Shape -> Shape
  translate v sh = Shape \ p -> inside (p `sub` v) sh
  
  union :: Shape -> Shape -> Shape
  union sh1 sh2 = Shape \ p -> inside p sh1 || inside p sh2
  
  intersect :: Shape -> Shape -> Shape
  intersect sh1 sh2 = Shape \ p -> inside p sh1 && inside p sh2
  
  invert :: Shape -> Shape
  invert sh = Shape \ p -> not (inside p sh)
  
  -- * Run function
  
  inside :: Point -> Shape -> Bool
  p `inside` Shape sh = sh p
  