Sei sulla pagina 1di 12

Foundations of Computer Science

11. Example: supermarket checkout

Summary: This lecture describes the construction of a Haskell program that specifies the behaviour of a supermarket checkout. Reference: Thompson Section 6.4

R.L. While & L. Barone, 20008

A supermarket checkout A supermarket checkout allows the operator to scan the barcodes of a basket of items, and produces an itemised bill for the customer The behaviour of the checkout is specified by a computer program The input to the checkout program is a sequence of the barcodes from the scanned items The output from the checkout program is a bill that gives the name and price of each scanned item, the total cost of the basket of items, and possibly other details of the transaction In this lecture we will develop a Haskell program for a supermarket checkout

Foundations of Computer Science

1 of 11

11. Example: supermarket checkout

A bill Bills are required to appear in this format


Haskell Stores Dry sherry, 1lt...........5.40 Fish fingers..............1.21 Orange jelly..............0.56 Hula hoops (giant)........1.33 Unknown item 1113.........0.00 Dry sherry, 1lt...........5.40 Total....................13.90

Foundations of Computer Science

2 of 11

11. Example: supermarket checkout

Types The first decision is how to represent the various sorts of objects used in the program The price of an item is best represented as an integer number of cents
type Price = Int

this allows more precision than using a real number The name of an item is represented as a string
type Name = String

A barcode is also represented as an integer


type Barcode = Int

The supermarket maintains a database that records the above three bits of information for each stocked item
type Item = (Barcode, Name, Price)

The supermarket's database is a collection of items


type Database = [Item]

The supermarket's database is represented by the function


database database :: Database -- database returns the supermarket's -- database of items

the full definition of database is given in the program Checkout.hs


3 of 11 11. Example: supermarket checkout

Foundations of Computer Science

Types contd. The basket of items bought by a customer is fed into the program as a sequence of barcodes
type Basket = [Barcode]

We also need an "internal" representation of a basket that contains the information required to print the bill for the basket
type BillType = [(Name, Price)]

We also define a function lineLength that specifies the width of the printed bill
lineLength :: Int -- lineLength returns the width of a bill lineLength = 30

The width is defined using a constant function for three reasons because the name lineLength is much easier to understand than a constant like 30, c.f. "magic numbers" so that all functions that use the width always refer to the same width, and so that it is easy to change the width when required only the definition of lineLength needs to be changed

Foundations of Computer Science

4 of 11

11. Example: supermarket checkout

The top-level function The top-level function of a program is the one that "calls" all of the other functions The top-level function for the checkout has the following definition
checkout :: Basket -> String -- checkout t returns the bill for t checkout t = formatBill (makeBill t)

Where does this equation come from? We have decomposed the problem into two parts makeBill uses the database to turn a Basket into the corresponding BillType
makeBill :: Basket -> BillType -- makeBill t returns the internal -- bill rep. for t

formatBill turns a BillType into the corresponding String

formatBill :: BillType -> String -- formatBill b returns the bill -- to be printed for b

Foundations of Computer Science

5 of 11

11. Example: supermarket checkout

Making a bill Making a bill (i.e. the internal rep.) involves searching the database for the information associated with each barcode in the basket
makeBill :: Basket -> BillType -- makeBill t returns the internal -- bill rep. for t makeBill t = [look database bc | bc <- t]

look is the function that actually does the searching given a barcode and a database, look locates all

entries in the database that refer to the barcode obviously there should be exactly one entry for each barcode, but

look :: Database -> Barcode -> (Name, Price) -- look d bc returns the name and price -- of bc in d look d bc | length nps == 1 = head nps | length nps == 0 = (unwords["Unknown item", show bc],0) | length nps > 1 = (unwords["Duplicated item",show bc],0) where nps = [(n, p) | (bc', n, p) <- d, bc' == bc]

here nps is a list containing every entry for bc in d

Foundations of Computer Science

6 of 11

11. Example: supermarket checkout

Formatting a bill A printed bill contains the title, one line for each item purchased, and one line for the total The title is just a string containing the name of the supermarket
formatTitle :: String -- formatTitle returns the title line -- for the bill formatTitle = "Haskell Stores"

The line for an item has lineLength characters in the following form
Fish fingers..............1.21

What parts are there in a line? the name of the item, some number of dots, and the price of the item So formatLine has the definition
formatLine :: (Name, Price) -> String -- formatLine np returns the line of -- the bill for np formatLine (n, p) = n ++ replicate (lineLength - length n - length p') '.' ++ p' where p' = formatPrice p

Foundations of Computer Science

7 of 11

11. Example: supermarket checkout

Formatting a bill
formatPrice turns a price into a string formatPrice :: Price -> String -- formatPrice p returns a string -- containing p formatPrice p = show (p `div` 100) ++ "." ++ formatCents (p `mod` 100) formatCents turns a number of cents into a string

we need to check if a leading zero is required

formatCents :: Int -> String -- formatCents x returns a string -- containing x formatCents x | x < 10 = '0' : show x | x >= 10 = show x formatLines returns a string containing the lines for all

of the individual items

formatLines :: BillType -> String -- formatLines b returns the lines -- for the individual items b formatLines b = unlines [formatLine np | np <- b]

Foundations of Computer Science

8 of 11

11. Example: supermarket checkout

Calculating and formatting the total The total is of course just the sum of the prices of the individual items
makeTotal :: BillType -> Price -- makeTotal b returns the total cost of b makeTotal b = sum [p | (n, p) <- b]

The line for the total has the following form


Total.....................1.21

The easiest way to format this is simply using


formatLine

why duplicate the effort? this approach (i.e. re-using formatLine) also guarantees consistency in the output

formatTotal :: Price -> String -- formatTotal p returns the line -- for the total p formatTotal p = formatLine ("Total", p)

Foundations of Computer Science

9 of 11

11. Example: supermarket checkout

Formatting the complete bill To recap: a printed bill contains the title, one line for each item purchased, and one line for the total formatBill "glues" all of the previous functions together to build these three components
formatBill :: BillType -> String -- formatBill b returns the bill -- to be printed for b formatBill b = unlines [formatTitle ,"" ,formatLines b ,"" ,formatTotal (makeTotal b)]

Foundations of Computer Science

10 of 11

11. Example: supermarket checkout

The complete program That completes the program! The complete program is available on the unit web-site

Foundations of Computer Science

11 of 11

11. Example: supermarket checkout

Potrebbero piacerti anche