
On Friday 07 May 2010 18:55:57, Payan Peshraw wrote:
Hi,
I have got a database with movies added into it. What Im basically coding is:
- add a new film to the database - display all the films - display all the films by a given director - display a list of user ratings (together with the users' names) for a given film - show the average overall rating for a given director - allow a given user to rate (or re-rate) a film (note that only the latest rating from the user should remain recorded) - display all the films from a given year, sorted in descending order of overall rating
Now I want to allow a given user to rate or be able to re-rate a film. But the latest rating from the user should remain recorder tho..and also I want to display all the films that a given user likes (i.e. the films to which she has given a positive-valued rating). I have written the code for the user liking the film but it doesn't seem to work and i'm not sure what to do with that one eiher.
Below is the coding that I've written so far, but i'm stuck on the last bit which I can't seem to code.
type Director = String type Title = String type Year = Int type Mark = Int type Rating = (String, Int)
type Film = (Title, Director, Year, [Rating])
Consider making Film an ADT, data Film = Film { title :: Title , director :: Director , year :: Year , ratings :: [Rating] } , maybe also Rating: type User = String data Rating = Rating { user :: User , rating :: Mark }
type Database = [Film]
testDatabase :: Database testDatabase = [("Casino Royale", "Martin Campbell", 2006, [("Garry",-8),("Dave", 0)]), ("Blade Runner", "Ridley Scott", 1982, [("Amy",5)]), ("The Fly", "David Cronenberg", 1986, [("Fred",7)]) ]
addFilm :: Database -> Title -> Director -> Year -> Database addFilm database title director year = (title, director, year, []): database
displayFilms :: Database ->[(Title, Director, Year, Mark)] displayFilms [] = [] displayFilms ((i, j, k, l):xs)
|l == [] = (i, j, k, 0) : displayFilms xs |otherwise = (i, j, k, overallRating l) : displayFilms xs
overallRating :: [Rating] -> Int overallRating rating = div (sum [j | (_,j) <- rating]) (length rating)
That gives an error for an empty list.
filmsByDirector :: Database -> Director -> Database filmsByDirector [] filmDirector = [] filmsByDirector((i, j, k, l):xs) filmDirector
|j == filmDirector = (i, j, k, l) : filmsByDirector xs | filmDirector otherwise = filmsByDirector xs | filmDirector
filmRating :: Database -> Title -> [Rating] filmRating [] filmRat = [] filmRating ((i,j, k, l):xs) filmRat
|i == filmRat = (l ++ filmRating xs filmRat) |otherwise = filmRating xs filmRat
THIS DOESNT SEEM TO WORK? {- filmsLiked :: Database -> String -> Database filmsLiked [] user = [] filmsLiked ((i,j,k,l):xs) user
| == user = i ++ filmsLiked xs user
That should of course be "i : filmsLiked xs user" if the function should return the list of titles of the films the user likes, "(i,j,k,l) : filmsLiked xs user" if it should return a Database (as the type signature says in accordance with the behaviour of filmsByDirector).
|otherwise = filmsLiked xs user
person :: [Rating] -> String -> Bool person [] userName = False person ((n, s):xs) userName
|n == userName && s > 0 = True |otherwise = person xs userName
-}
You have the function which tells you whether a user liked a film (more precisely, whether a list of Ratings contains a positive rating from a user). The name of that function is very inappropriate, though. Use that to write likes :: User -> Film -> Bool likes user (t,d,y,rs) = ??? And then use that in filmsLiked, filmsLiked :: Database -> User -> Database filmsLiked (film : rest) user | user `likes` film = ??? | otherwise = filmsLiked rest user filmsLiked [] _ = []
averageDirector :: Database -> Director -> Int averageDirector [] directorRating = 0 averageDirector ((i,j,k,l):xs) directorRating
|j == directorRating = (overallRating l) + | (averageDirector xs directorRating) otherwise = | averageDirector xs directorRating
filmFromYear :: Database -> Year -> Database filmFromYear [] filmYear = [] filmFromYear ((i,j,k,l):xs) filmYear
|k == filmYear = (i,j,k,l) : filmFromYear xs | filmYear otherwise = filmFromYear xs filmYear
rateFilm :: [Rating] -> Rating -> [Rating] rateFilm [] rating = rating:[] rateFilm ((user, rating):xs) (newUser, newRating)
|newUser == user = ((newUser, newRating):xs) |otherwise = (user, rating) : (rateFilm xs (newUser, | newRating))
Stuck on this bit.. {- changeFilm :: Database -> Title -> [Rating] -> Database changeFilm ......... -}
What is that supposed to do?
Any help is appreciated..thank you!
Generally, - the use of i, j, k, l as parameter names is bad. If you want to use one- letter parameters, pick the initials of their meaning, (t, d, y, r) is in this context much better. (title, director, year, ratings) still better. - the argument order of your functions is irritating. It would be more natural to have the Database as the last argument. - the code could be much improved by * using as-patterns, e.g. filmsByDirector (film@(_,d,_,_) : rest) dir | d == dir = film : filmsByDirector rest dir | otherwise = filmsByDirector rest dir * using functions like filter, e.g. filmsByDirector db dir = filter (dir `isDirector`) db where isDirector name (_,d,_,_) = name == d * using list-comprehensions, e.g. filmsByDirector db dir = [film | film@(_,d,_,_) <- db, dir == d]