[英]Film database in Haskell
目前正在尝试解决我的haskell程序中的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.