import Word
import Bits

-- #1 
data Color = Red | Orange | Yellow | Green | Blue | Indigo | Violet
  deriving Show -- for testing
instance Eq Color where
  x == y = fromEnum x == fromEnum y
  
instance Ord Color where
  compare x y = compare (fromEnum x) (fromEnum y)

instance Enum Color where
  fromEnum Red = 0
  fromEnum Orange = 1
  fromEnum Yellow = 2
  fromEnum Green = 3
  fromEnum Blue = 4
  fromEnum Indigo = 5
  fromEnum Violet = 6
  toEnum 0 = Red
  toEnum 1 = Orange
  toEnum 2 = Yellow
  toEnum 3 = Green
  toEnum 4 = Blue
  toEnum 5 = Indigo
  toEnum 6 = Violet
  enumFrom x = enumFromTo x maxBound
  enumFromThen x y = enumFromThenTo x y lastColor
		     where lastColor = if y < x then minBound else maxBound

-- not asked for by problem, but gives neater solution to enumFrom[Then], above.
instance Bounded Color where
  minBound = Red
  maxBound = Violet

-- #2


type Bytestream = [Word8]  
class Serializable a where
  serialize :: a -> Bytestream 
  deserialize :: Bytestream -> (a,Bytestream)

instance Serializable Char where 
  serialize c = [intToWord8 (ord c)]
  deserialize (b:bs) = (chr (word8ToInt b),bs)

instance Serializable Int where 
  serialize i = map word32ToWord8 [w .&. 0xff, 
				  (w .&. 0xff00) `shiftR` 8,
			          (w .&. 0xff0000) `shiftR` 16,
		                  (w .&. 0xff000000) `shiftR` 24]
	    where w = intToWord32 i	       
  deserialize (b0:b1:b2:b3:bs) = (i, bs)
            where i = word32ToInt ((word8ToWord32 b0) .|. 
				   ((word8ToWord32 b1) `shiftL` 8) .|. 
		                   ((word8ToWord32 b2) `shiftL` 16) .|. 
				   ((word8ToWord32 b3) `shiftL` 24))

instance Serializable a => Serializable (Maybe a) where
  serialize (Just x) = 1:(serialize x)
  serialize Nothing = [0]
  deserialize (1:bs) = let (x,bs') = deserialize bs in (Just x,bs')
  deserialize (0:bs) = (Nothing,bs)

instance Serializable a => Serializable [a] where
  serialize l = serialize (length l) ++ (concat (map serialize l))
  deserialize bs = get len bs' []
     where len :: Int
           (len,bs') = deserialize bs
           get 0 bs rs = (reverse rs,bs)
           get n bs rs = let (r,bs') = deserialize bs in get (n-1) bs' (r:rs)

-- testing:

a :: Char 
a = 'a'
b :: [Int]
b = [-101,104] 
c :: Maybe String
c = Just "pdq"
bytes ::  Bytestream
bytes =  serialize a  ++  serialize b ++ serialize c

a':: Char 
(a',rest1) = deserialize bytes
b' :: [Int]
(b',rest2) = deserialize rest1
c' :: Maybe String
(c',rest3) = deserialize rest2

ok = a == a' && b == b' && c == c' && rest3 == []


ok' = x == x' && rest == []
  where
    x :: Maybe [[Maybe Char]]
    x = Just [[Just 'a',Nothing, Just 'b'],[Just 'c']]
    bytes = serialize x
    x' :: Maybe [[Maybe Char]]
    (x',rest) = deserialize bytes
