-- Definition of List from lecture
data List = Empty | Cons Integer List deriving Show
-- example list for testing
list = Cons 1 (Cons 7 (Cons 9 (Cons 3 Empty)))
-- example assignment for testing
myAssn = Assign "x" 1 (Assign "x" 2 (Assign "y" 3 EmptyA))

-- Exercise 1

-- disj
disj :: Bool -> Bool -> Bool
disj = undefined

-- sumList
sumList :: List -> Integer
sumList = undefined

-- double2nd
double2nd :: List -> List
double2nd = undefined


-- Exercise 3

data Expr = Number Integer
  | Var String
  | Plus Expr Expr
  | Negate Expr
  deriving Show
  
data Assignment = EmptyA | Assign String Integer Assignment
  deriving Show

ite :: Bool -> Integer -> Integer -> Integer
ite b x y = undefined

lookupA :: Assignment -> String -> Integer
lookupA assn s = undefined

eval :: Assignment -> Expr -> Integer
eval assn e = undefined
  

-- Exercise 3.4

{- You may (and will have to) extend this datatype in order to incorporate the "let" construct. -}
data Expr' = Number' Integer
  | Var' String
  | Plus' Expr' Expr'
  | Negate' Expr'
  deriving Show
  
eval' :: Assignment -> Expr' -> Integer
eval' assn e = undefined


-- the following tests can be used by you, once you have implemented your functions,
-- for testing, just invoke testX in ghci
testSum = putStrLn ("expected: 20\ncomputed: " ++ show (sumList list))
testDouble = putStrLn ("expected: Cons 1 (Cons 14 (Cons 9 (Cons 6 Empty)))\ncomputed: " ++ show (double2nd list))
testLookupA = putStrLn ("expected: 1 3 0\ncomputed: " ++ show (lookupA myAssn "x") ++ " " ++ show (lookupA myAssn "y") ++ " " ++ show (lookupA myAssn "z"))
testEval = putStrLn ("expected: 42\ncomputed: " ++ show (eval myAssn (Plus (Negate (Var "y")) (Number 45))))