2014-03-14 52 views
0

我剛剛意識到我一直在錯誤地做這件事。Haskell在不更改代碼的情況下刪除數據庫變量

我創建了與testDatabase相關的功能。然而,我也將其包含在函數中,但我想更改它,以便功能代碼稍後可以與任何數據庫一起運行,而不僅僅涉及testDatabase,因爲現在正在執行一些功能。

通過從一些函數中刪除testDatabase我會得到錯誤,因此只需要一些幫助來修改和修復此問題以備將來參考。我已經吸取了教訓,不要在函數中使用實際的測試數據庫。

我怎樣才能改變我的代碼,以便testDatabase不在功能,但在演示它涉及到它類似於演示1,7和77

我沒有問題,徹底改變了代碼,但我只是在尋找一個快速修復。

我希望我已經正確地解釋了這一點。

import Data.List 
import Text.Printf 
import Data.Ord 
import Data.Char 

type Rating = (String, Int) 
type Title = String 
type Director = String 
type Year = Int 
type Film = (Title, Director, Year,[Rating]) 

testDatabase :: [Film] 
testDatabase = [("Blade Runner","Ridley Scott",1982,[("Amy",6), ("Bill",9), ("Ian",7), ("Kevin",9), ("Emma",4), ("Sam",5), ("Megan",4)]), 
       ("The Fly","David Cronenberg",1986,[("Megan",4), ("Fred",7), ("Chris",5), ("Ian",0), ("Amy",5)]), 
       ("Psycho","Alfred Hitchcock",1960,[("Bill",4), ("Jo",4), ("Garry",8), ("Kevin",7), ("Olga",8), ("Liz",10), ("Ian",9)]), 
       ("Body Of Lies","Ridley Scott",2008,[("Sam",3), ("Neal",7), ("Kevin",2), ("Chris",5), ("Olga",6)]), 
       ("Avatar","James Cameron",2009,[("Olga",2), ("Wally",8), ("Megan",9), ("Tim",5), ("Zoe",8), ("Emma",3)]), 
       ("Titanic","James Cameron",1997,[("Zoe",7), ("Amy",2), ("Emma",5), ("Heidi",3), ("Jo",8), ("Megan",5), ("Olga",7), ("Tim",10)]), 
       ("The Departed","Martin Scorsese",2006,[("Heidi",2), ("Jo",8), ("Megan",5), ("Tim",2), ("Fred",5)]), 
       ("Aliens","Ridley Scott",1986,[("Fred",8), ("Dave",6), ("Amy",10), ("Bill",7), ("Wally",2), ("Zoe",5)]), 
       ("Prometheus","Ridley Scott",2012,[("Garry",3), ("Chris",4), ("Emma",5), ("Bill",1), ("Dave",3)]), 
       ("E.T. The Extra-Terrestrial","Steven Spielberg",1982,[("Ian",7), ("Amy",2), ("Emma",7), ("Sam",8), ("Wally",5), ("Zoe",6)]), 
       ("The Birds","Alfred Hitchcock",1963,[("Garry",7), ("Kevin",9), ("Olga",4), ("Tim",7), ("Wally",3)]), 
       ("Goodfellas","Martin Scorsese",1990,[("Emma",7), ("Sam",9), ("Wally",5), ("Dave",3)]), 
       ("The Shawshank Redemption","Frank Darabont",1994,[("Jo",8), ("Sam",10), ("Zoe",3), ("Dave",7), ("Emma",3), ("Garry",10), ("Kevin",7)]), 
       ("Gladiator","Ridley Scott",2000,[("Garry",7), ("Ian",4), ("Neal",6), ("Wally",3), ("Emma",4)]), 
       ("The Green Mile","Frank Darabont",1999,[("Sam",3), ("Zoe",4), ("Dave",8), ("Wally",5), ("Jo",5)]), 
       ("True Lies","James Cameron",1994,[("Dave",3), ("Kevin",4), ("Jo",0)]), 
       ("Minority Report","Steven Spielberg",2002,[("Dave",5), ("Garry",6), ("Megan",2), ("Sam",7), ("Wally",8)]), 
       ("The Wolf of Wall Street","Martin Scorsese",2013,[("Dave",6), ("Garry",6), ("Megan",0), ("Sam",4)]), 
       ("War Horse","Steven Spielberg",2011,[("Dave",6), ("Garry",6), ("Megan",3), ("Sam",7), ("Wally",8), ("Zoe",8)]), 
       ("Lincoln","Steven Spielberg",2012,[("Ian",3), ("Sam",7), ("Wally",3), ("Zoe",4), ("Liz",7), ("Megan",4)]), 
       ("Vertigo","Alfred Hitchcock",1958,[("Bill",7), ("Emma",5), ("Zoe",9), ("Olga",6), ("Tim",10)]), 
       ("The Terminal","Steven Spielberg",2004,[("Olga",3), ("Heidi",8), ("Bill",2), ("Sam",6), ("Garry",8)]), 
       ("Jaws","Steven Spielberg",1975,[("Fred",3), ("Garry",0), ("Jo",3), ("Neal",9), ("Emma",7)]), 
       ("Hugo","Martin Scorsese",2011,[("Sam",4), ("Wally",3), ("Zoe",4), ("Liz",7)])] 

------------------------------------------------------------ 
-----------------FUNCTIONAL CODE---------------------------- 
------------------------------------------------------------     

--when adding need to be addFilm string string int and the list name called testDatabase 
addFilm :: String -> String -> Int -> [Film] -> [Film] 
addFilm title director year database = (title, director, year, []) : database 

--Some functions needed later on: 
averageFilmRating :: [(String,Int)] -> Float 
averageFilmRating ratings 
    = (fromIntegral(sum $ map snd ratings))/(fromIntegral(length ratings)) 

--Formats the films for decimal, gives average rating of films instead of all users ratings. 
formatFilmOutput :: Film -> String 
formatFilmOutput (title, director, year, rating) 
    = printf "%s by %s. Year: %d, Average Rating: %.1f\n" (title) (director) (year) (averageFilmRating rating) 

--Shows all films in the database  
displayAllFilm :: [Film] -> [Film] 
displayAllFilm list = list 


--Shows films by director name 
displayByDirector :: String -> [Film] 
displayByDirector name 
    = filter(\(_,director,_,_) -> director == name) testDatabase 

--Gives the average of directors films 
directorAverage :: String -> Float 
directorAverage dir 
    = averageFilmRating [rating | (title, director, year, ratings) <- displayByDirector dir, rating <- ratings] 

--These two functions give the films rated of average 6 or over 
filmsRated :: Int -> [Film] 
filmsRated rating 
     = filter(\(_,_,_,a) -> averageFilmRating a >= fromIntegral rating) testDatabase 

filmsaveragesix = filmsRated 6 

--Shows what films the user has rated. 
userRatedFilms :: String -> [Film] 
userRatedFilms username 
    = filter ((username `elem`) . (\(_,_,_,xs) -> map fst xs)) testDatabase 

-- Allows user to rate or re-rate film. 
databaseNoFilm:: [Film] -> Title -> [Film] 
databaseNoFilm database t = [(title, director, year, ratings) | (title, director, year, ratings) <- database, title /= t] 
rateFilm :: [Film] -> Title -> Rating -> [Film] 
rateFilm database findtitle (u, r) = databaseNoFilm database findtitle ++ [(title,director,year,(u, r):[(username,rtg) | (username,rtg) <- ratings, username /= u]) | (title, director, year, ratings) <- database, title == findtitle] 

--Displays films by year in descending order of rating 
filmsByYear :: Int -> [Film] 
filmsByYear year = sortFilms $ filter(\(_,_,yr,_) -> yr >= year) testDatabase 

sortFilms :: [Film] -> [Film] 
sortFilms = sortBy $ flip $ comparing averageFilmRating' 
    where 
    averageFilmRating' (_,_,_,rs) = averageFilmRating rs 

------------------------------------------------------------ 
-----------------DEMO FUNCTION------------------------------ 
------------------------------------------------------------ 
demo :: Int -> IO() 
demo choice = do 
    case choice of 
     1 -> do 
      putStrLn $ unlines $ map formatFilmOutput $ addFilm "Gravity" "Alfonso Cuaron" 2013 testDatabase 
     2 -> do 
      putStrLn (unlines $ map formatFilmOutput $ displayAllFilm testDatabase) 
     3 -> do 
      putStrLn (unlines (map formatFilmOutput(displayByDirector "James Cameron"))) 
     4 -> do 
      putStrLn (unlines (map formatFilmOutput(filmsaveragesix))) 
     5 -> do 
      print $ directorAverage "James Cameron" 
     6 -> do 
      print $ userRatedFilms "Zoe" 
     7 -> do 
      print $ rateFilm testDatabase "Jaws" ("Zoe", 8) 
     77 -> do 
      print $ rateFilm testDatabase "Vertigo" ("Zoe", 3)   
     8 -> do 
      putStrLn (unlines (map formatFilmOutput(filmsByYear 2009))) 
+0

您需要在'demo'中使用'State' monad並使用例如'modify'(http://hackage.haskell.org/package/mtl-1.1.0.2/docs/Control-Monad-State- Class.html#v:modify)來更改狀態並通過'get'來提供狀態。對於當前直接訪問'testDatabase'的函數,您還需要將其作爲參數。 – kvanberendonck

+0

PS你的一些'type'同義詞可能會從記錄或至少newtype(因爲'type'不是「安全的」)中受益。 – kvanberendonck

+0

我不認爲你說的是​​必要的。我確信現在有一種更簡單的方法,我現在無法想到它。也許我需要一個數據構造函數? – user3411002

回答

1

發送testDatabase作爲參數。例如:

--Displays films by year in descending order of rating 
filmsByYear :: Int -> [Film] -> [Film] 
filmsByYear year database = sortFilms $ filter(\(_,_,yr,_) -> yr >= year) database 

然後加入testDatabase任何代碼調用這個函數:

putStrLn (unlines (map formatFilmOutput(filmsByYear 2009 testDatabase))) 

做相同的userRatedFilmsdisplayByDirector

+0

這是我最初做的,因此在這裏被問到了錯誤。看來我忘了參數[電影]。這樣愚蠢的錯誤!謝謝你的幫助! – user3411002

相關問題