簡體   English   中英

Haskell的電影數據庫

[英]Film database in Haskell

目前正在嘗試解決我的haskell程序中的2個主要問題。

  1. 顯示給定用戶喜歡的所有電影
  2. 顯示在特定期間(即在給定的開始年份和結束年份之間)放映的給定演員的所有電影。

這是我當前正在使用的示例數據庫:

type Title = String
type Cast = String
type Year = Int
type Fans = String

type Film = (Title, [Cast], Year, [Fans])
type Database = [Film]

testDatabase :: Database
testDatabase = [("Casino Royale", ["Daniel Craig", "Eva Green", "Judi Dench"], 2006,    ["Garry", "Dave", "Zoe", "Kevin", "Emma"]),
("Cowboys & Aliens", ["Harrison Ford", "Daniel Craig", "Olivia Wilde"], 2011, ["Bill", "Jo", "Garry", "Kevin", "Olga", "Liz"]),     
    ("Catch Me If You Can", ["Leonardo DiCaprio", "Tom Hanks"], 2002, ["Zoe", "Heidi", "Jo", "Emma", "Liz", "Sam", "Olga", "Kevin", "Tim"])]    

數據庫更大,但是出於空間原因,我省略了一些。

  • 現在如何使用該數據庫創建回答以上兩個問題所需的功能?

這是對第一個問題的簡短回答。 這看起來像作業,所以您應該嘗試自己解決第二個問題!

fan y = map (\(a,_,_,_) -> a) $ filter (\(_,_,_,a) -> elem y a) testDatabase

重要的部分是:

elem測試y是否是列表a的成員-即電影是否在其粉絲列表中包含用戶。

filter接受一個謂詞和一個列表,並僅返回該列表中滿足該謂詞的項目。

map接受一個函數和一個列表,然后將該函數應用於列表。 這僅用於提取電影的標題。

您應該能夠使用類似的方法來回答第二個問題。

這應該工作:

type Title = String
type Actor = String
type Cast = [Actor]
type Year = Int
type Fan = String
type Fans = [Fan]
type Period = (Year, Year)
type Film = (Title, Cast, Year, Fans)
type Database = [Film]

testDatabase :: Database
testDatabase = [("Casino Royale", ["Daniel Craig", "Eva Green", "Judi Dench"], 2006, ["Garry", "Dave", "Zoe", "Kevin", "Emma"]),
                ("Cowboys & Aliens", ["Harrison Ford", "Daniel Craig", "Olivia Wilde"], 2011, ["Bill", "Jo", "Garry", "Kevin", "Olga", "Liz"]),     
                ("Catch Me If You Can", ["Leonardo DiCaprio", "Tom Hanks"], 2002, ["Zoe", "Heidi", "Jo", "Emma", "Liz", "Sam", "Olga", "Kevin", "Tim"])]

inCast :: Actor -> Film -> Bool
inCast givenActor (_, cast, _, _) = any (\actor -> actor == givenActor) cast

inPeriod :: Period -> Film -> Bool
inPeriod (periodStart, periodEnd) (_, _, year, _) = periodStart <= year && year <= periodEnd

inCastAndPeriod :: Actor -> Period -> Film -> Bool
inCastAndPeriod actor period film = inCast actor film && inPeriod period film

isFan :: Fan -> Film -> Bool
isFan givenFan (_, _, _, fans) = any (\fan -> fan == givenFan) fans

allFilmsThatAGivenUserIsAFanOf :: Fan -> [Film]
allFilmsThatAGivenUserIsAFanOf givenFan = filter (isFan givenFan) testDatabase

allTheFilmsOfAGivenActorThatWereReleasedDuringAParticularPeriod :: Actor -> Period -> [Film]
allTheFilmsOfAGivenActorThatWereReleasedDuringAParticularPeriod givenActor givenPeriod = filter (inCastAndPeriod givenActor givenPeriod) testDatabase

祝好運!

如果您將Film類型聲明為記錄,您將免費獲得現場訪問者,這將使過濾器更易於閱讀(而且, Fans不是一個Fan嗎?):

type Title = String
type Cast = String
type Year = Int
type Fan = String

data Film = Film { filmTitle :: Title
                 , filmCast  :: [Cast]
                 , filmYear  :: Year
                 , filmFans  :: [Fan]
                 }

type Database = [Film]

你的第一個問題,說你想要的Film S的給定的用戶是一個Fan (不的標題Film S):

fanOfFilms :: Fan -> Database -> [Film]
fanOfFilms fan = filter (elem fan . filmFans)

您的第二個問題可以用相同的方式解決,但謂詞變得更加復雜:

periodActorOfFilms :: Cast -> Year -> Year -> Database -> [Film]
periodActorOfFilms actor startYear endYear =
    filter $ \film -> and [ actor `elem` filmCast film
                          , startYear <= filmYear film
                          , endYear >= filmYear film
                          ]

如果使用以下類型聲明,則此解決方案有效。 代數類型更好地實現了此類功能。

-- Types
type Title   = String
type Actor   = String
type Year    = Int
type Fan     = String

-- Film type
data Film    = Film Title [Actor] Year [Fan]
                deriving (Eq,Ord,Show,Read)

-- converts a list of strings to string through recursion and pattern matching.
displayListAsString :: [String] -> String
displayListAsString [] = ""
displayListAsString (x:[]) = x ++ displayListAsString []
displayListAsString (x:xs) = x ++ ", " ++ displayListAsString xs

-- Give all films that a particular user is a fan of.
isFanOfMovies :: Fan -> [Film] -> String
isFanOfMovies fanName [] = "No Database provided."
isFanOfMovies fanName movieDB = moviesAsString $ isFanOf fanName movieDB

-- filters through the database to find the films which a particular user is a fan of.
isFanOf :: Fan -> [Film] -> [Film]
isFanOf fanName = filter (\(Film _ _ _ fans) -> elem fanName fans)

-- displays a movie as well formatted string
movieAsString :: Film -> String
movieAsString (Film title cast year fans) = "\nTitle: " ++ title ++ "\n Cast: " ++ 
(displayListAsString cast) ++ "\n Year: " ++ show year ++ 
"\n Fans: " ++ show (length fans)

-- Gives all films in the database (if database passed through directly)
moviesAsString :: [Film] -> String
moviesAsString movieDB = (unlines.map movieAsString) movieDB

作為一項附加功能,您可以使用以下內容首先檢查風扇是否存在,然后如果返回值“”,則系統將繼續獲取膠片。 但這是當您要實現用戶界面時使用的。

fanFilms (fanName, database) = do
let fan = fanExists fanName database
    if fan == ""
        then do
            putStrLn "\nDisplaying all the films you're a fan of below:"
            putStrLn $ isFanOfMovies fanName database
            return (fanName, database)
        else do
            putStrLn "No Results Found.\n"
            putStrLn $ fanExists fanName database
            return (fanName, database)

-- This can be used to check if the fan exists.
fanExists :: Fan -> [Film] -> String
fanExists fanName movieDB
    | isFanOf fanName movieDB == []     = "No movies you are fan of."
    | otherwise                         = ""

已經晚了一年,但希望對您所有的mathfun都有用;)

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM