Instead of taking a lucrative summer job at the company across the lake, you become the wine steward at the Internet Cafe. In keeping with the ambiance of the job, you decide to write an internet shopping agent to track down the best buys for wines from on-line merchants. Needless to say, after your experience in CSE341, you decide to do the project in ML.
A major portion of the program is a collection of routines which parse web pages and identify the wines being sold. A difficulty is that each web site has its own format for information, so it is necessary to write some code specific to each web site being searched. Of course, the hope is to write as little page specific code as possible, and to use general search routines for most of the work.
For the assignment, you are to write two functions: findWine, which, given a query string and a list of files, returns a list of wines satisfying the query, and printWineList, which displays a list of wines.
findWine : ( string * ( string * fileCode ) list ) -> wine list
printWineList : wine list -> bool
datatype fileCode = VirtualVineyard | WineConnection | RedCarpet;
val myIOList = [ ("vv1.html", VirtualVineyard), ("wc1.html", WineConnection),
("wc2.html", WineConnection), ("rc1.html", RedCarpet),
("rc2.html", RedCarpet), ("rc3.html", RedCarpet)];
The keywords may appear in any order. An example query string is "Vintage 1995 Type Merlot MinPrice 8 MaxPrice 11"
An example that uses the {} delimiters is "Vintage 1995 Type {Pinot Gris} Minprice 8 MaxPrice 11"
The result of the query would be a list of all 1995 Merlot's priced between $8 and $11.
The keywords are Vintage, Winery, Variety, Location, MinPrice, MaxPrice, Merchant.
If a keyword is not present, the corresponding attribute is unconstrained, so if Vintage is not present, then any year is okay.
You may assume that each keyword appears at most once in a query string. (Although it would be really cool to allow and/or/not and other higher-order queries. You are allowed to do more than the assignment asks - although it is a good strategy to get the basic stuff working before additional features).
Keywords:
One way to deal with multiword names is to use just a single word for input and searching, but the multiword name for output. For example, the user would enter Variety Noir instead of Variety {Pinot Noir} to get a listing of the Pinot Noirs, although the output routine could use the name Pinot Noir. Note that some web pages use abbreviations.
Here is a sample interaction with the system:
- val myIOlist = [ ("vv1.html", VintageVineyards) ];
val myIOlist = [("vv1.html",VintageVineyards)] : (string * fileCode) list
- val myQuery = "Variety Soave Vintage 1673 MinPrice 800";
val myQuery = "Variety Soave Vintage 1673 MinPrice 800" : string
- val wines = findWine (myQuery, myIOlist);
val wines = : wine list
- printWineList wines;
... ...
val it = () : unit
You should not turn in web pages - only your code, a description of what your code does, and output from sample runs. Also, make sure that your code doesn't produce reams of debugging output.
Read chapter 9 of Ullman for a discussion of the IO functions. Craig will either cover this topic in section on Tuesday or find some other way to help everyone out.
You _are_ expected to write clean ML code in a functional style. You are expected to make appropriate use of pattern matching, datatypes and higher-order functions.
fullWineList : (string * fileCode) list -> wine list findWine : ( string * wine list ) -> wine list [ Or the curried version, findWine : string -> wine list -> wine list] printWineList : wine list -> bool
Script started on Sun Apr 13 11:05:08 1997 % /cse/courses/cse341/97wi/sml/sml Standard ML of New Jersey, Version 0.93, February 15, 1993 val it = () : unit - use "wino.ml"; [opening wino.ml] [opening utility.ml] [opening query.ml] [opening parse.ml] val iList = [(VirtualVineyard,"vv1.html"),(WineConnection,"wc1.html"), (WineConnection,"wc2.html"),(WineConnection,"wc3.html"), (WineConnection,"wc4.html"),(RedCarpet,"rc1.html"),(RedCarpet,"rc2.html"), (RedCarpet,"rc3.html"),(RedCarpet,"rc4.html"),(RedCarpet,"rc5.html")] : (merchant * string) list - val fl = fullWineList iList; val fl = [(VirtualVineyard,Chardonnay,1995,20),(VirtualVineyard,PinotNoir,1995,20), (VirtualVineyard,Chardonnay,1994,22),(VirtualVineyard,Chardonnay,1993,19), (VirtualVineyard,Chardonnay,1995,15),(VirtualVineyard,Chardonnay,1994,35), (VirtualVineyard,Chardonnay,1994,23),(VirtualVineyard,Chardonnay,1995,12), (VirtualVineyard,PinotNoir,1994,13),(VirtualVineyard,Chardonnay,1994,32), (VirtualVineyard,Chardonnay,1995,19),(VirtualVineyard,PinotNoir,1994,24), ...] : (merchant * wineVariety * int * int) list - val w1 = findWine "variety pinot vintage 1995" fl; val w1 = [(VirtualVineyard,PinotNoir,1995,20),(VirtualVineyard,PinotNoir,1995,16), (VirtualVineyard,PinotNoir,1995,14),(VirtualVineyard,PinotNoir,1995,14), (VirtualVineyard,PinotNoir,1995,18),(VirtualVineyard,PinotNoir,1995,14), (VirtualVineyard,PinotNoir,1995,17),(VirtualVineyard,PinotNoir,1995,11), (VirtualVineyard,PinotNoir,1995,12),(VirtualVineyard,PinotNoir,1995,12)] : (merchant * wineVariety * int * int) list - printWineList w1; Virtual Vinyard has a 1995 Pinot Noir for $20 Virtual Vinyard has a 1995 Pinot Noir for $16 Virtual Vinyard has a 1995 Pinot Noir for $14 Virtual Vinyard has a 1995 Pinot Noir for $14 Virtual Vinyard has a 1995 Pinot Noir for $18 Virtual Vinyard has a 1995 Pinot Noir for $14 Virtual Vinyard has a 1995 Pinot Noir for $17 Virtual Vinyard has a 1995 Pinot Noir for $11 Virtual Vinyard has a 1995 Pinot Noir for $12 Virtual Vinyard has a 1995 Pinot Noir for $12 val it = [] : 'a list - fun wineBot str = printWineList (findWine str fl); val wineBot = fn : string -> 'a list - wineBot "variety Pinot minPrice 20"; Virtual Vinyard has a 1995 Pinot Noir for $20 Virtual Vinyard has a 1994 Pinot Noir for $24 Virtual Vinyard has a 1994 Pinot Noir for $30 Virtual Vinyard has a 1994 Pinot Noir for $25 Virtual Vinyard has a 1993 Pinot Noir for $21 Virtual Vinyard has a 1992 Pinot Noir for $23 Virtual Vinyard has a 1994 Pinot Noir for $25 Virtual Vinyard has a 1993 Pinot Noir for $26 Virtual Vinyard has a 1994 Pinot Noir for $24 Virtual Vinyard has a 1994 Pinot Noir for $20 val it = [] : 'a list - wineBot "variety pino vint 1994 minprice 17 maxprice 23"; Virtual Vinyard has a 1994 Pinot Noir for $20 val it = [] : 'a list - wineBot "variety chardonnay vintage 1993"; Virtual Vinyard has a 1993 Chardonnay for $19 Virtual Vinyard has a 1993 Chardonnay for $15 Virtual Vinyard has a 1993 Chardonnay for $17 Virtual Vinyard has a 1993 Chardonnay for $24 val it = [] : 'a list - wineBot "minPrice 100"; Virtual Vinyard has a 1991 Chardonnay for $469 val it = [] : 'a list - wineBot "maxPrice 10"; Virtual Vinyard has a 1995 Chardonnay for $9 Virtual Vinyard has a 1994 Chardonnay for $4 val it = [] : 'a list - % script done on Sun Apr 13 11:27:22 1997