{-# 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)

