Created
August 8, 2013 09:12
-
-
Save sjoness/6183027 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| module Main where | |
| import System.IO | |
| -- Extended exercise: supermarket billing | |
| -- ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | |
| -- Types of names, prices (pence) and bar-codes. | |
| type Name = String | |
| type Price = Int | |
| type BarCode = Int | |
| -- The database linking names prices and bar codes. | |
| type Database = [ (BarCode,Name,Price) ] | |
| -- The example database we use is | |
| codeIndex :: Database | |
| codeIndex = [ (4719, "Fish Fingers" , 121), | |
| (5643, "Nappies" , 1010), | |
| (3814, "Orange Jelly", 56), | |
| (1111, "Hula Hoops", 21), | |
| (1112, "Hula Hoops (Giant)", 133), | |
| (1234, "Dry Sherry, 1lt", 540)] | |
| -- The lists of bar codes, and of Name,Price pairs. | |
| type TillType = [BarCode] | |
| type BillType = [(Name,Price)] | |
| -- The length of a line in the bill. | |
| lineLength :: Int | |
| lineLength = 30 | |
| formatPence :: Price -> String | |
| formatPence p = | |
| let | |
| pounds = p `div` 100 | |
| pence = p `mod` 100 | |
| padding | pence < 10 = "0" | |
| | otherwise = "" | |
| in | |
| show pounds ++ "." ++ padding ++ show pence | |
| formatLine :: (Name,Price) -> String | |
| formatLine (n,p) = | |
| let | |
| ln = length n | |
| fp = formatPence p | |
| lp = length fp | |
| dots = replicate (lineLength - ln - lp) '.' | |
| in | |
| n ++ dots ++ fp ++ "\n" | |
| formatLines :: BillType -> String | |
| formatLines nps = concat [ formatLine np | np <- nps ] | |
| makeTotal :: BillType -> Price | |
| makeTotal nps = sum ps | |
| where | |
| (_,ps) = unzip nps | |
| formatTotal :: Price -> String | |
| formatTotal p = "\n" ++ formatLine ("Total",p) | |
| formatBill :: BillType -> String | |
| formatBill nps = formatLines nps ++ | |
| formatTotal (makeTotal nps) | |
| look :: Database -> BarCode -> (Name,Price) | |
| look db bc = head ([ (n,p) | (c,n,p) <- db, c==bc ] ++ [ui]) | |
| where | |
| ui = ("Unknown Item", 0) | |
| lookUp :: BarCode -> (Name, Price) | |
| lookUp bc = look codeIndex bc | |
| makeBill :: TillType -> BillType | |
| makeBill tt = map lookUp tt | |
| ----------------------------------------------------------- | |
| -- drs | |
| -- added code for interactive program | |
| ----------------------------------------------------------- | |
| readDB :: IO Database | |
| readDB = do | |
| contents <- readFile "db.txt" | |
| let getProduct line = let [barcode,name,price] = words line | |
| in (read barcode,read name,read price) | |
| return [ getProduct line | line <- lines contents ] | |
| scan :: IO Int | |
| scan = do putStr "Scan > " | |
| c <- getLine | |
| return (read c) | |
| scans :: IO [Int] | |
| scans = do bc <- scan | |
| if bc == 0 | |
| then return [] | |
| else do | |
| bcs <- scans | |
| return (bc:bcs) | |
| main = do hSetBuffering stdout NoBuffering | |
| bcs <- scans | |
| putStr (formatBill (makeBill bcs)) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment