content: {-# LANGUAGE ExistentialQuantification #-}
  -- !!! Tests existential data types
  --     Originally from Kevin Glynn
  module Main(main) where
  
  data Coordinate3D = Coord3D {cx, cy, cz::Double} 
                      deriving (Eq, Show)
  
  -- We Represent a line by two coordinates which it passes through.
  data Line = MkLine Coordinate3D Coordinate3D 
  
  
  class PictureObject pot where
  
        -- Returns ordered (rel to 0 0 0) of points where the object
        -- intersects the given line. 
        intersectLineObject :: pot -> Line -> [Coordinate3D]
  
        getPictureName :: pot -> String
  
  data Sphere = 
     Sphere Coordinate3D			-- Centre
            Double			-- Radius
  	  Double			-- ambient coeff
  	  Double			-- diffuse coeff
  	  Double			-- specular coeff
  	  Double			-- phong specular exponent
  
  intersectLineSphere :: Sphere -> Line -> [Coordinate3D]
  intersectLineSphere sp line = []
  
  instance PictureObject Sphere where
   	 intersectLineObject = intersectLineSphere
  	 getPictureName _ = "Sphere"
  
  data Cube = 
     Cube Coordinate3D		-- Origin corner 
          Coordinate3D		-- Opposite corner
  	Double			-- ambient coeff
  	Double			-- diffuse coeff
  	Double			-- specular coeff
  	Double			-- phong specular exponent
     deriving (Eq, Show)
  
  intersectLineCube :: Cube -> Line -> [Coordinate3D]
  intersectLineCube cube line = []
  
  instance PictureObject Cube where
  	 intersectLineObject = intersectLineCube
  	 getPictureName _ = "Cube"
  
  
  data GenPic = forall pot. (PictureObject pot) => MkGenPic pot
  
  sphere :: Sphere
  sphere = Sphere (Coord3D 1 1 1) 1 1 1 1 1
  
  cube :: Cube
  cube = Cube (Coord3D 1 1 1) (Coord3D 2 2 2) 1 1 1 1
  
  obj_list:: [GenPic] 
  obj_list = [MkGenPic sphere, MkGenPic cube]
  
  putName :: PictureObject pot => pot -> IO ()
  putName x = putStr $ getPictureName x
  
  
  main :: IO ()
  main = do { sequence_ $ map put_it obj_list }
       where
         put_it (MkGenPic s) = putStrLn (getPictureName s)
  
  