CS计算机代考程序代写 database Haskell cache — Remember: there are many possible solutions, and if your solution produces

— Remember: there are many possible solutions, and if your solution produces
— the right results, then it is (most likely) correct. However, if your code
— looks far more complicated than these sample solutions, then you’re probably
— making things too difficult for yourself—try to keep it simple!
module Resit where

import Data.Maybe (catMaybes)
import Data.List (transpose)
import System.Random
import Text.Printf (printf)

— Importing the keymap module

import KeymapList
— import KeymapTable

— Type declarations
type Barcode = String
type Name = String
type Price = Int — in pence
type Item = (Name, Price)
type Catalogue = Keymap Barcode Item

— A little test catalog
testDB :: Catalogue
testDB = fromList
[ (“0265090316581”, (“Talisker Single Malt Whisky”, 2900))
, (“0903900739533”, (“Bagpipes of Glory”, 1000))
, (“9780201342758”, (“Hutton – Programming in Haskell”, 3500))
, (“0042400212509”, (“Frying pan”, 750))
]

— Show pence as pounds with two decimal points
showPrice :: Int -> String
showPrice total = printf “£%d.%02d” pounds pence
where (pounds, pence) = total `divMod` 100

— Show an item as a list of strings, to be padded later
showItem :: (Barcode, Item) -> [String]
showItem (k, (n, p)) = [k , n , showPrice p]

pad :: Int -> String -> String
pad n s = s ++ replicate (n – length s) ‘ ‘

showCatalogue :: Catalogue -> String
showCatalogue c = format (map showLine ls)
where
ls = [“Key”, “Name”, “Price”] : map showItem (toList c)

— Compute the limits of each column.
limits = map ((+ 3) . maximum . map length) (transpose ls)

— Show a single line, padding each entry appropriately (depending on its column).
showLine :: [String] -> String
showLine = concat . zipWith pad limits

— Add vertical line to the final output.
format :: [String] -> String
format (x:xs) = unlines (x:vline:xs)
where vline = replicate (sum limits) ‘-‘

{-
*Resit> putStrLn (showCatalogue testDB)
Key Name Price
———————————————————–
0265090316581 Talisker Single Malt Whisky £29.00
0903900739533 Bagpipes of Glory £10.00
9780201342758 Hutton – Programming in Haskell £35.00
0042400212509 Frying pan £7.50
-}

— * Exercise 1: Displaying customer orders.

type Quantity = Int
type Order = [(Barcode, Quantity)]

testOrder :: Order
testOrder =
[ (“0265090316581”, 2)
, (“9780201342758”, 1)
]

showItem’ :: ((Name, Price, Quantity), Int, Int) -> [String]
showItem’ = undefined

showOrder :: Catalogue -> Order -> String
showOrder = undefined

{-
*Resit> putStrLn (showOrder testDB testOrder)
Name Qty Rate Amount Running Sum
————————————————————————
Talisker Single Malt Whisky 2 £29.00 £58.00 £58.00
Hutton – Programming in Haskell 1 £35.00 £35.00 £93.00
————————————————————————
VAT (20%) + £18.60
= £111.60
-}

— * Exercise 2: Retrieving list of items using the Keymap API.

getItems :: [Barcode] -> Catalogue -> [Item]
getItems = undefined

— * Exercise 3: Benchmarking the list implementation.

{-
*Resit> :set +s
*Resit> db <- readDB Done (??? secs) *Resit> ks <- samples 1000 db (??? secs) *Resit> force (getItems ks db)
()
(??? secs)
-}

— * Exercise 8: Benchmarking the hash-table implementation.

{-
*Resit> :r
[2 of 3] Compiling KeymapTable ( KeymapTable.hs, interpreted )
[3 of 3] Compiling Resit ( Resit.hs, interpreted )
Ok, three modules loaded.
*Resit> db <- readDB Done (??? secs) *Resit> ks <- loadKeys (??? secs) *Resit> force (getItems ks db)
()
(??? secs)
*Resit>
-}

— ** Input-output

readDB :: IO Catalogue
readDB = do dbl <- lines <$> readFile “database.csv”
let db = fromList (map readLine dbl)
putStrLn (size db >= 0 `seq` “Done”)
return db

readLine :: String -> (Barcode, Item)
readLine s = (i, (n, read p))
where
(i, s’) = splitUpon ‘,’ s
(n, p) = splitUpon ‘,’ s’

splitUpon :: Char -> String -> (String,String)
splitUpon _ “” = (“”,””)
splitUpon c (x:xs) | x == c = (“”,xs)
| otherwise = (x:ys,zs)
where
(ys,zs) = splitUpon c xs

samples :: Int -> Catalogue -> IO [Barcode]
samples n db =
do g <- newStdGen let allKeys = [ key | (key,item) <- toList db ] let indices = randomRs (0, length allKeys - 1) g let keys = take n [ allKeys !! i | i <- indices ] saveKeys keys return (force keys `seq` keys) saveKeys :: [Barcode] -> IO ()
saveKeys = writeFile “keys.cache” . show

loadKeys :: IO [Barcode]
loadKeys = do
keys <- read <$> readFile “keys.cache”
return (force keys `seq` keys)

force :: [a] -> ()
force = foldr seq ()