user2240649
user2240649

Reputation: 89

Haskell finding information in a database

I currently have a database with this information:

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]
title (t, _, _, _) = t
fans (_, _, _, fs) = fs
year (_, _, y, _) = y

    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"]),           
                ("Mamma Mia!", ["Meryl Streep", "Pierce Brosnan"], 2008, ["Kevin", "Jo", "Liz", "Amy", "Sam", "Zoe"]),     
                    ("Saving Private Ryan", ["Tom Hanks", "Matt Damon"], 1998, ["Heidi", "Jo", "Megan", "Olga", "Zoe", "Wally"]),         
                        ("Life of Pi" ,["Suraj Sharma"], 2012, ["Kevin", "Olga", "Liz", "Tim", "Zoe", "Paula", "Jo", "Emma"])]

Note: The testDatabase contains much more data and I have only included a snippet of this.

Now my aim is to write a function that allows me to "display the best film" according to the number of fans.

I have tried using 'length fans' to output the size of fans per film but I don't know how to get around then outputting the Title of the 'best film'

Here is an example code to displayAllFilms:

displayAllFilms' :: [Film] -> String -> String
displayAllFilms' [] filmString = filmString
displayAllFilms' ((title,cast,year,fans):films) filmString = 
       displayAllFilms' films (filmString ++ "\n" ++ title ++ ", " ++ listStuff cast ", " ++ (show year) ++ ", " ++ show (length fans))

To which it outputs the number of fans per film...

Edit:

I forgot to mention the function requires the user to enter an actors name to which it then outputs best film according to the amount of fans that film has and the actor starrs in.

Any help would be much appreciated, Thanks!

Upvotes: 1

Views: 309

Answers (1)

Jakub
Jakub

Reputation: 507

There are a couple of already predefined functions (maximumBy and comparing) that could be useful for you.

maximumBy :: (a -> a -> Ordering) -> [a] -> a
comparing :: Ord a => (b -> a) -> b -> b -> Ordering

In order to select the film with the most fans you could write:

import Data.List
import Data.Ord

bestFilm :: Database -> Film
bestFilm = maximumBy $ comparing (length . fans)

It can be easily translated into plain English: "Select the maximum film by comparing the lengths of the fan lists".

Note that in serious scenarios lists are completely unsuitable for representing a database. You should use sorted and/or indexed data structures.

Edit:

To select only from films containing a specific actor you can filter the films first.

filmsWithActor :: Actor -> Database -> Database
filmsWithActor actor = filter $ \film -> actor `elem` cast film

cast (_, c, _, _) = c

Upvotes: 1

Related Questions