简体   繁体   中英

Haskell printing all elements of a list within tuple

I'm trying to print all elements of the Fans list for a given film title for example all fans of "Avatar" not quite sure how to filter this and display the correct elements as a string. Here is the type definition of the program with some of the test data.

import Data.Char
import Data.List

--types
type Title = String
type Director = String
type Year = Int
type Fans = [String]

type Film = (Title, Director, Year, Fans)

type Database = [Film]

testDatabase :: [Film]
testDatabase = [
 ("Blade Runner", "Ridley Scott", 1982, ["Zoe", "Heidi", "Jo", "Kate", "Emma", "Liz", "Sam", "Olga", "Tim"]),
 ("The Fly", "David Cronenberg", 1986, ["Garry", "Dave", "Zoe", "Kevin", "Emma"]),
 ("Body Of Lies", "Ridley Scott", 2008, ["Bill", "Olga", "Tim", "Zoe", "Paula"]),
 ("Avatar", "James Cameron", 2009, ["Dave", "Amy", "Liz"]),
 ("Titanic", "James Cameron", 1997, ["Zoe", "Emma", "Paula", "Liz", "Olga", "Dave"])]

You're really shooting yourself in the foot by using type synonyms for everything. data Film = Film Title Director Year Fans is much better than using a tuple in this case. Defining a separate Film data type brings the semantic difference between a Film and a tuple of Title , Director , Year , and Fans into the type system. This means that you can define instances for it (like Show or Eq ) that will behave in a specific way that is different from what a tuple would give you. It also causes the compiler to reject code that (potentially accidentally) mixes a tuple that happens to have the type (String,String,Int,[String]) with an actual Film . This adds safety, which is one of the main reasons to use Haskell in the first place.

That said, listing the fans only is pretty simple either way:

listFans :: Film -> String
-- data way
listFans (Film _ _ _ fans) = intersperse ',' fans
-- tuple way
listFans (_,_,_,fans) = intersperse ',' fans

Next, we need a lookupFilm :: Database -> Title -> Maybe Film to find the film we want. We need the Maybe because the Film might not be in the Database .

lookupFilm :: Database -> Title -> Maybe Film
lookupFilm db t = find (\(Film t' _ _ _) -> t == t') db

Note that this doesn't "print" the strings, it just returns them, so you would need putStrLn . listFans :: Film -> IO () putStrLn . listFans :: Film -> IO () to actually output them.

If you always lookup films by their title, you might as well use a Map Title Film from Data.Map .

Lastly: be sure you understand how find and intersperse work; Data.List is like being given a fish, but you need to learn how to fish for yourself in order to tackle more complex problems as they arise.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM