======= 6. Programming with ADTs ======= 1. A **dictionary** is a collection of key-value pairs, which we can represent in Haskell as a list of pairs ''(String,Integer)'' where ''String'' is the key type and ''Integer'' is the value type: type Dict = [(String,Integer)] Implement the function ''valueOf'' which takes a key and a dictionary, and returns the associated value. It is guaranteed that the value exists. valueOf :: String -> Dict -> Integer 2. Implement the function ''ins'' which takes a key ''s'', a value ''i'', a dictionary ''d'' and updates the value of ''s'' in the dictionary, if the value exists, or adds the key-value pair, otherwise. For instance ''ins "x" 1 [("x",0)] = [("x",1)]'' and ''ins "x" 1 [("y",0)] = [("x",1),("y",0)]''. ins :: String -> Integer -> Dict -> Dict 3. Consider the type ''PExpr'' of //program expressions// defined in the lecture. Implement a function for showing ''PExpr'' values: data PExpr = Val Integer | Var String | PExpr :+: PExpr show_pexpr :: PExpr -> String 4. Implement a function which takes a dictionary of program variables, a program expression ''PExpr'', and evaluates it. For instance: ''eval_pexpr [("x",2),("y",1)] ( (Var "x") :+: (Var "y") )'' returns 3. eval_pexpr :: Dict -> PExpr -> Integer 5. Consider the type ''BExpr'' of **boolean expressions** defined in the lecture. Implement a function for displaying values of ''BExpr'': data BExpr = PExpr :==: PExpr | PExpr :<: PExpr | Not BExpr | BExpr :&&: BExpr show_bexpr :: BExpr -> String Add the following code to your program: instance Show PExpr where show = show_pexpr instance Show BExpr where show = show_bexpr 6. Write a function which, given a dictionary, evaluates boolean conditions ''BExpr'': eval_bexpr :: Dict -> BExpr -> Bool Add the following code (from the lecture) to your program: data Prog = PlusPlus Var | -- x++; Var :=: PExpr | -- x = ; DeclareInt Var | -- int x; Begin Prog Prog | --

While BExpr Prog | -- while () {

} If BExpr Prog Prog -- if () {

} else { } show_p :: Prog -> String show_p (PlusPlus v) = v++"++;\n" show_p (x :=: e) = x++"="++(show_pexpr e)++";\n" show_p (DeclareInt x) = "int "++x++";\n" show_p (Begin p p') = (show_p p)++(show_p p') show_p (While e p) = "while ("++(show_bexpr e)++") {\n"++(show_p p)++"}\n" show_p (If e p p') = "if ("++(show_bexpr e)++") {\n"++(show_p p)++"}\n else {\n"++(show_p p')++"}\n" instance Show Prog where show = show_p 7. Define the program: int x; x++; while (x < 100){ x = x + 1 } 8. Define a function ''eval'' which takes a dictionary and a program, and evaluates the program under the given dictionary. The function will return an updated dictionary. For instance: eval [("x",0)] (PlusPlus "x") = [("x",1)] eval [("x",1)] ("x" :=: ((Var "x") :+: (Val 1))) = [("x",2)] eval [] (DeclareInt "x") = [("x",0)] eval :: Dict -> Prog -> Dict Add the following error-handling type to your program: data Result a = Error String | -- a value of type (Result a) is an error, or Value a -- an actual value, wrapped by the data constructor Value 9. Implement the function ''check'' which takes a list of **defined** variables, a program ''p'', and returns an updated list of variable definitions, if ''p'' does not contain undeclared variables, and an error message, otherwise. check :: [Var] -> Prog -> Result [Var] For instance: check [] (DeclareInt "x") = Value ["x"] check [] (PlusPlus "x") = Error "x is undefined" check ["x"] (PlusPlus "x") = ["x"]