I. Review of material on following the grammar A. Lists ------------------------------------------ LIST GRAMMAR ::= ------------------------------------------ What's the grammar for lists? ------------------------------------------ HOW TO KNOW WHICH ARGUMENT TO RECUR ON? FOR YOU TO DO Write: addLists :: (Num t) => [t] -> [t] -> [t] which adds two lists of numbers. It has the following tests: module AddListsTests where import Testing import AddLists main = dotests "AddListsTests $Revision$" [eqTest (addLists [] []) "==" [] ,eqTest (addLists [1] [1]) "==" [2] ,eqTest (addLists [2,1] [3,1]) "==" [5,2] ,eqTest (addLists [2,1] [3,1]) "==" [5,2] ,eqTest (addLists [1 .. 10] [7,8]) "==" [8,10] ,eqTest (addLists [7,8] [1 .. 10]) "==" [8,10] ,eqTest (addLists [1 .. 10] [91 .. 100]) "==" [92, 94 .. 110] ] ------------------------------------------ B. Boolean Expression grammar ------------------------------------------ GRAMMAR FOR Bexp module Bexp where data Bexp = And Bexp Bexp | Or Bexp Bexp | Not Bexp | Comp Comparison deriving (Eq, Show) data Comparison = Equals String String | NotEquals String String deriving (Eq, Show) ------------------------------------------ What are some examples in this grammar? ------------------------------------------ FOR YOU TO DO Write negateBexp :: Bexp -> Bexp that produces a Bexp that is the negation of its argument. Test cases: [(eqTest (negateBexp (Comp (Equals "q" "q"))) "==" (Comp (NotEquals "q" "q"))) ,(eqTest (negateBexp (Comp (NotEquals "x" "y"))) "==" (Comp (Equals "x" "y"))) ,(eqTest (negateBexp (Not (Comp (Equals "q" "r")))) "==" (Comp (Equals "q" "r"))) ,(eqTest (negateBexp (And (Comp (NotEquals "p" "q")) (Comp (Equals "x" "x")))) "==" (Or (Comp (Equals "p" "q")) (Comp (NotEquals "x" "x")))) ,(eqTest (negateBexp (Or (Comp (Equals "p" "q")) (Comp (NotEquals "x" "x")))) "==" (And (Comp (NotEquals "p" "q")) (Comp (Equals "x" "x")))) ,(eqTest (negateBexp (And (Not (Comp (Equals "p" "p"))) (Or (Comp (Equals "y" "x")) (And (Comp (Equals "a" "b")) (Comp (NotEquals "z" "q")))))) "==" (Or (Comp (Equals "p" "p")) (And (Comp (NotEquals "y" "x")) (Or (Comp (NotEquals "a" "b")) (Comp (Equals "z" "q")))))) ,(eqTest (negateBexp (Not (And (Not (Comp (Equals "p" "p"))) (Comp (Equals "x" "x"))))) "==" (And (Not (Comp (Equals "p" "p"))) (Comp (Equals "x" "x")))) ,(eqTest (negateBexp (Or (Not (And (Not (Comp (Equals "p" "p"))) (Comp (Equals "x" "x")))) (Or (Comp (Equals "p" "q")) (Comp (Equals "x" "x"))))) "==" (And (And (Not (Comp (Equals "p" "p"))) (Comp (Equals "x" "x"))) (And (Comp (NotEquals "p" "q")) (Comp (NotEquals "x" "x"))))) ] ------------------------------------------ How many functions should be written for this? What's the outline of the function(s)? C. Statements and Expressions grammar ------------------------------------------ STATEMENTS AND EXPRESSIONS GRAMMAR module StatementsExpressions where data Statement = ExpStmt Expression | AssignStmt String Expression | IfStmt Expression Statement deriving (Eq, Show) data Expression = VarExp String | NumExp Integer | EqualsExp Expression Expression | BeginExp [Statement] Expression deriving (Eq, Show) ------------------------------------------ ------------------------------------------ GRAMMAR FOR REPRESENTING TYPES module StatementsExpressionsTypes (module StatementsExpressions, module StatementsExpressionsTypes) where import StatementsExpressions data SEType = TInt | TBool | TVoid | TWrong deriving (Eq, Show) ------------------------------------------ ------------------------------------------ FOR YOU TO DO Write a function seTypeCheckExp :: TTypeEnv -> Expression -> SEType type TTypeEnv = String -> SEType where the TTypeEnv argument tells the type of each variable (a String). Tests: myte :: TTypeEnv myte v = case v of "i" -> TInt "j" -> TInt "b" -> TBool _ -> TWrong main = dotests "SETypeCheckTests $Revision$" [eqTest (seTypeCheckExp myte (VarExp "i")) "==" TInt ,eqTest (seTypeCheckExp myte (VarExp "j")) "==" TInt ,eqTest (seTypeCheckExp myte (VarExp "b")) "==" TBool ,eqTest (seTypeCheckExp myte (NumExp 4020)) "==" TInt ,eqTest (seTypeCheckExp myte (EqualsExp (NumExp 4020) (NumExp 0))) "==" TBool ,eqTest (seTypeCheckExp myte (EqualsExp (VarExp "b") (EqualsExp (NumExp 0) (NumExp 4020)))) "==" TBool ,eqTest (seTypeCheckExp myte (EqualsExp (VarExp "b") (VarExp "i"))) "==" TWrong ,eqTest (seTypeCheckExp myte (BeginExp [] (VarExp "b"))) "==" TBool ,eqTest (seTypeCheckExp myte (BeginExp [(AssignStmt "b" (EqualsExp (NumExp 0) (VarExp "i")))] (VarExp "b"))) "==" TBool ,eqTest (seTypeCheckStmt myte (AssignStmt "i" (EqualsExp (VarExp "w") (VarExp "i")))) "==" TWrong ,eqTest (seTypeCheckExp myte (BeginExp [(AssignStmt "i" (EqualsExp (VarExp "w") (VarExp "i"))) ,(AssignStmt "b" (EqualsExp (NumExp 0) (VarExp "i")))] (VarExp "b"))) "==" TWrong ,eqTest (seTypeCheckStmt myte (AssignStmt "i" (NumExp 4020))) "==" TVoid ,eqTest (seTypeCheckStmt myte (ExpStmt (NumExp 4020))) "==" TVoid ,eqTest (seTypeCheckStmt myte (ExpStmt (EqualsExp (NumExp 4020) (VarExp "b")))) "==" TWrong ,eqTest (seTypeCheckStmt myte (IfStmt (NumExp 1) (AssignStmt "i" (NumExp 4020)))) "==" TWrong ,eqTest (seTypeCheckStmt myte (IfStmt (VarExp "b") (AssignStmt "i" (NumExp 4020)))) "==" TVoid ] ------------------------------------------ How many functions to write for this? What's the outline? Should we do another Statements and Expressions problem? D. Window Layouts 1. Haskell Records ------------------------------------------ RECORDS IN HASKELL Data type declarations can define which can be used to make data WindowLayout = Window {wname :: String, width :: Int, height :: Int} | Horizontal [WindowLayout] | Vertical [WindowLayout] deriving (Show, Eq) Patterns in case expressions use syntax: { [ = ,] ... } as in: case wl of (Window {wname = n, width = w, height = h}) -> ... (Horizontal wls) -> ... Construction uses similar syntax: (Window {wname = "abc", width = 50, height = 50}) ------------------------------------------ 2. the window layout type ------------------------------------------ WINDOW LAYOUT TYPE module WindowLayout where data WindowLayout = Window {wname :: String, width :: Int, height :: Int} | Horizontal [WindowLayout] | Vertical [WindowLayout] deriving (Show, Eq) Examples: ------------------------------------------ What are some examples of expressions that have this type? 3. total width problem ------------------------------------------ FOR YOU TO DO Write a function totalWidth :: WindowLayout -> Int that gives the width of a WindowLayout for Window it's the width of that for Horizonatl, it's the sum of their widths for Vertical, it's the max of their widths Tests: module TotalWidthTests where import Testing import WindowLayout import TotalWidth main = dotests "TotalWidthTests $Revision: 1.1 $" tests tests :: [TestCase Int] tests = [(eqTest (totalWidth (Window {wname = "olympics", width = 50, height = 33})) "==" 50) ,(eqTest (totalWidth (Horizontal [])) "==" 0) ,(eqTest (totalWidth (Vertical [])) "==" 0) ,(eqTest (totalWidth (Horizontal [(Window {wname = "olympics", width = 80, height = 33}) ,(Window {wname = "news", width = 20, height = 10})])) "==" 100) ,(eqTest (totalWidth (Vertical [(Window {wname = "olympics", width = 80, height = 33}) ,(Window {wname = "news", width = 20, height = 10})])) "==" 80) ,(eqTest (totalWidth (Vertical [(Window {wname = "Star Trek", width = 40, height = 100}) ,(Window {wname = "olympics", width = 80, height = 33}) ,(Window {wname = "news", width = 20, height = 10})])) "==" 80) ,(eqTest (totalWidth (Horizontal [(Vertical [(Window {wname = "Tempest", width = 200, height = 100}) ,(Window {wname = "Othello", width = 200, height = 77}) ,(Window {wname = "Hamlet", width = 1000, height = 600})]) ,(Horizontal [(Window {wname = "baseball", width = 50, height = 40}) ,(Window {wname = "track", width = 100, height = 60}) ,(Window {wname = "golf", width = 70, height = 30})]) ,(Vertical [(Window {wname = "Star Trek", width = 40, height = 100}) ,(Window {wname = "olympics", width = 80, height = 33}) ,(Window {wname = "news", width = 20, height = 10})]) ])) "==" 1300) ] ------------------------------------------ How many functions should there be? What would be the outline? E. Sales Data examples ------------------------------------------ SALES DATA TYPE module SalesData where data SalesData = Store { address :: String, amounts :: [Int] } | Group { gname :: String, members :: [SalesData] } deriving (Show, Eq) ------------------------------------------ ------------------------------------------ FOR YOU TO DO Write a function normalizeSalesData :: SalesData -> SalesData that returns the arguement with - the address of each store capitalized - the name of each group capitalized - with only the first 5 elements of the amounts in each store retained Use Data.Char.toUpper to do capitalization Tests: module NormalizeSalesDataTests where import Testing import SalesData import NormalizeSalesData main = dotests "$Revision: 1.2 $" tests tests = [(eqTest (normalizeSalesData (Store {address = "1005 Alafaya Trail Rd." ,amounts = [101, 102, 103, 104, 105, 106]})) "==" (Store {address = "1005 ALAFAYA TRAIL RD." ,amounts = [101, 102, 103, 104, 105]})) ,(eqTest (normalizeSalesData (Store {address = "227 International Dr." ,amounts = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]})) "==" (Store {address = "227 INTERNATIONAL DR." ,amounts = [1, 2, 3, 4, 5]})) ,(eqTest (normalizeSalesData (Group {gname = "Target" ,members = [(Store {address = "227 International Dr." ,amounts=[1,2,3,4,5,6,7,8,9,10]}) ,(Store {address = "1005 Alafaya Trail Rd." ,amounts=[101,102,103,104,105,106]})]})) "==" (Group {gname = "TARGET" ,members = [(Store {address = "227 INTERNATIONAL DR." ,amounts=[1,2,3,4,5]}) ,(Store {address = "1005 ALAFAYA TRAIL RD." ,amounts=[101,102,103,104,105]})]})) ,(eqTest (normalizeSalesData (Group {gname = "Target" ,members = [(Group {gname = "Target Florida" ,members = [(Store {address="227 International Dr." ,amounts=[1,2,3,4,5,6,7,8,9,10]}) ,(Store {address="1005 Alafaya Trail Rd." ,amounts=[101,102,103,104,105,106]})]}) ,(Group {gname = "Target Iowa" ,members = [(Store {address="1024 Binary Ave." ,amounts=[1,2,4,8]}) ,(Store {address="256 Logical Blvd." ,amounts=[7,25,15,44,36,8,3,7]})]}) ,(Group {gname = "Target New York" ,members = [(Group {gname = "Target NYC" ,members = [(Store {address = "Fifth Ave." ,amounts= [8,2,1,3,3,5]}) ,(Store {address= "Albany" ,amounts = []})]})]})]}))) "==" (Group {gname = "TARGET" ,members= [(Group {gname = "TARGET FLORIDA" ,members = [(Store {address = "227 INTERNATIONAL DR." ,amounts=[1,2,3,4,5]}) ,(Store {address = "1005 ALAFAYA TRAIL RD." ,amounts=[101,102,103,104,105]})]}) ,(Group {gname = "TARGET IOWA" ,members = [(Store {address = "1024 BINARY AVE." ,amounts=[1,2,4,8]}) ,(Store {address = "256 LOGICAL BLVD." ,amounts=[7,25,15,44,36]})]}) ,(Group {gname = "TARGET NEW YORK" ,members= [(Group {gname = "TARGET NYC" ,members = [(Store {address= "FIFTH AVE." ,amounts=[8,2,1,3,3]}) ,(Store {address="ALBANY" ,amounts=[]})]})]})]})] module NormalizeSalesDataInClass (normalizeSalesData) where import SalesData import Data.Char (toUpper) ------------------------------------------ How many functions should there be? What's the outline?