2013-04-03 3 views
1

В настоящее время вы пытаетесь решить 2 основных вопроса в моей программе haskell.База данных фильмов в Haskell

  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"])]  

база данных гораздо больше, но по космическим причинам я пропустил некоторые из этого.

  • Как создать функции, необходимые для ответа на 2 вопроса выше, используя эту базу данных?
+2

Что вы пробовали? Знаете ли вы о функции ['filter'] (http://www.haskell.org/ghc/docs/latest/html/libraries/base/Prelude.html#v:filter)? – dave4420

+0

Это домашнее задание? –

+0

Привет, Я знаю о функции фильтра, но я не знаю, как реализовать это в этом сценарии. Это не домашнее задание, а фактическая помощь для целей пересмотра. – user2240649

ответ

1

Вот очень короткий ответ на ваш первый вопрос. Это похоже на домашнюю работу, поэтому вы должны попытаться решить вторую самостоятельно!

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

Важные детали:

elem испытания y является ли элемент списка a - то есть, содержит ли пленка пользователя в своем списке поклонников.

filter берет предикат и список и возвращает только элементы в этом списке, удовлетворяющие предикату.

map принимает функцию и список и применяет эту функцию к списку. Это используется для извлечения только названия фильма.

Вы должны иметь возможность использовать аналогичный подход для ответа на второй вопрос.

+0

Спасибо за помощь, я попытаюсь применить это ко второму вопросу – user2240649

1

Это должно работать:

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 

Удачи!

+0

Спасибо за помощь! :) – user2240649

0

Если объявить 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 сек которых данный пользователь является Fan (не титулы Film ы):

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 
          ] 
+0

спасибо за помощь, я попробую и интерпретирую ваш ответ, чтобы я мог это понять :) – user2240649

+0

Это, похоже, не работает с моей текущей базой данных, которую я предоставил выше, мне нужно манипулировать текущей базой данных, чтобы она работала с вашим кодом? – user2240649

+0

Пленки больше не являются кортежами, теперь они должны быть построены с помощью конструктора 'Film'. Просто удалите парсеры и запятые из каждого кортежа и поставьте «Фильм» перед каждым: «Фильм« Казино Рояль »[« Дэниел Крейг »,« Ева Грин »,« Джуди Денч »] 2006 [« Гарри », Dave "," Zoe "," Kevin "," Emma "]' – pat

0

Это решение работает, если вы используете следующие декларации типов. Алгебраический тип намного лучше реализует такие функции.

-- 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 много;)

Смежные вопросы