--
{-  From the prelude, so we can't redefine
class Eq a where
    (==), (/=) :: a -> a -> Bool
    x /= y      = not (x==y)


class (Eq a) => Ord a where
    compare    :: a -> a -> Ordering
    (<), (<=), (>=), (>)  :: a -> a -> Bool
    max, min              :: a -> a -> a
-}


-------- Equality over Arithmetic Expressions

data Aop = Add | Sub | Mult | Div
data Aexp = Num Int | Exp (Aexp, Aop, Aexp)

int_eq :: Int -> Int -> Bool
int_eq x y = x==y

aop_eq Add Add = True
aop_eq Sub Sub = True
aop_eq Mult Mult = True
aop_eq Div Div = True
aop_eq _ _ = False

aexp_eq (Num x) (Num y) = int_eq x y
aexp_eq (Exp(e1,x,e2))(Exp(f1,y,f2))
  = (aexp_eq e1 f1) &&
    (aop_eq x y) &&
    (aexp_eq e2 f2)
aexp_eq _ _ = False


instance Eq(Aop) where
  x == y = aop_eq x y
  x /= y = not(aop_eq x y )

instance Eq(Aexp) where
  x == y = aexp_eq x y
  x /= y = not(aexp_eq x y )

------The Complex Example

data Complex = C Float Float

complex_add (C x y) (C a b) = C (x+a) (y+b)

complex_sub (C x y) (C a b) = C (x-a) (y-b)

complex_mult (C x y) (C a b)
     = C (x*a - y*b) (x*b + a*y)


instance Eq(Complex) where
    (C x y) == (C a b) = x==a && y==b

instance Show(Complex)  where
    showsPrec = error "No show for complex"
    showList = error "No show for complex"

instance Num(Complex) where
  x + y = complex_add x y
  x - y = complex_sub x y
  x * y = complex_mult x y

 {- The full Num class from the prelude so it can't be redefined. Use comment
 class (Eq a, Show a) => Num a where
     (+), (-), (*)  :: a -> a -> a
     negate         :: a -> a
     abs, signum    :: a -> a
     fromInteger    :: Integer -> a
     fromInt        :: Int -> a

     x - y           = x + negate y
     fromInt         = fromIntegral
-}


---------- Ordering of trees
data Tree a = Leaf a | Branch (Tree a) (Tree a)

instance Eq a => Eq (Tree a) where
  (Leaf x) == (Leaf y) = x==y
  (Branch x y) == (Branch a b) = x==a && y==b
  _ == _ = False


instance (Ord a,Eq a) => Ord(Tree a) where
  (Leaf _) < (Branch _ _) = True
  (Leaf x) < (Leaf y)     = x < y
  (Branch _ _) < (Leaf _) = False
  (Branch l1 r1) < (Branch l2 r2)
       = if l1==l2
            then r1 < r2
            else l1 < l2

  t1 <= t2 = t1 < t2 || t1 == t2

-------- Classes for type constuctors - Motivation
data Mylist a = Nil | Cons a (Mylist a)

int_list_eq(Nil, Nil) = True
int_list_eq(Cons x xs, Cons y ys) =
   (int_eq x y) && (int_list_eq(xs,ys))
int_list_eq (_, _) = False

list_eq :: (a -> b -> Bool) -> (Mylist a,Mylist b) -> Bool
list_eq f (Nil, Nil) = True
list_eq f (Cons x xs, Cons y ys) =
    (f x y) && (list_eq f (xs, ys))
list_eq f (_, _) = False


instance Eq a => Eq(Mylist a) where
   Nil == Nil                 = True
   (Cons x xs) == (Cons y ys) = (x == y) && (xs == ys)
   _ == _                    = False

--------------- The Bush type. Soemthing to think about

data Bush a = One a
            | Two (Bush a) (Bush a)
            | Many [Bush a]

instance (Eq a) => Eq(Bush a)  where
  (One x) == (One y) = (x == y)
  (Two x1 x2) == (Two y1 y2) = (x1 == y1) && (x2 == y2)
  (Many xs) == (Many ys) = (xs == ys)
  _ == _ = False


------ The class MyShow a simplification of the Class Shoe

class MyShow a where
    myshow :: a -> String
    myshows :: a -> String -> String

name = "Tim"
age = 9

test = "My name is" ++ show name ++ "I am" ++ show age ++ "years old"

instance MyShow a => MyShow (Tree a) where
  myshow (Leaf x) = "(Leaf " ++ myshow x ++ ")"
  myshow (Branch x y) =
    "(Branch" ++ myshow x ++ myshow y ++ ")"

showsTree :: MyShow a => Tree a -> String -> String
showsTree (Leaf x) s = "(Leaf " ++ myshow x ++ ")" ++ s
showsTree (Branch x y) s =
  "(Branch" ++ (showsTree x (showsTree y (")" ++ s)))


showsList [] s     = s
showsList (x:xs) s = shows x (showsList xs s)


-------- Derived Instances

data Color = Red | Orange | Yellow | Green
           | Blue |Indigo | Violet
  deriving Show

data Exp = Int Int | Plus Exp Exp | Minus Exp Exp
  deriving (Eq,Show)

-------- Propogating qualified types

member x [] = False
member x (z:zs) =
    if x==z then True else member x zs

--