0

type UserRatings = (String,Int)
type Film = (Title, Director, Year , [UserRatings])

I am trying to use proper the printF method for the IO but i cant figure out what is going wrong. I know the problem has to do with the userRatings.

In the neo.txt there are 25 films of type Film I am trying to print them in the user interface menu that I made.

The user types main -> then his username -> then the option choice "2" and then the films are supposed to be displayed.

    displayFilmsIO :: Database -> IO()
    displayFilmsIO [] = putStrLn "There are no films in the database"
    displayFilmsIO filmList = sequence_[printf("|%-25s| |%-65s| |%-10d| |(%s,%d) |\n") title director year [(name,rating)] | (title, director, year, [(name,rating)]) <- filmList] 

    mainMenu :: [Film] -> String -> IO()
    mainMenu list user  = do
        putStrLn "What do you want to do ?(choose one of the options below)"
        putStrLn "[1] Add a film to the database \n[2] View all Films \n[3] View all films that you are fan of of\n[4] View all fans of a particular film \n[5] View all the films that were released during a particular period\n[6] Be a fan of a particular film\n[7] View the average number of fans for the films starring a particular actor \n[8] View the names of actors who have co-starred in at least one film with a particular actor \n[9] Save \n[0] Exit"
        putStrLn "__________________________________"
        choice <-getLine
        case choice of
             "2" -> do
                printf ("|%-25s| |%-65s| |%-10d| | %s,%d |\n") "Title" "Cast" "Year" "Fans"
                displayFilmsIO list
                mainMenu list user

And this is the main method. Nothing wrong with it, it compiles but just so you have more info.

main :: IO ()
main = do
    films <- loadFile2
    getName2 films

loadFile :: FilePath -> IO (Either ParseError [Film])
loadFile filename = do
  handle <- openFile filename ReadMode
  !database <- hGetContents handle
  hClose handle
  return $ parse films "Films" database

loadFile2 :: IO [Film]
loadFile2 = do
    allFilms <- readFile "neo.txt"
    let films = read allFilms :: [Film]
    return films

getName2 :: [Film] -> IO ()
getName2 films = do

1 Answer 1

3

The snippet

printf("|%-25s| |%-65s| |%-10d| |(%s,%d) |\n") title director year [(name,rating)]

looks wrong: 5 format string % arguments, but 4 arguments. Maybe you want

printf("|%-25s| |%-65s| |%-10d| |(%s,%d) |\n") title director year name rating

?

Also, the whole list comprehension looks wrong:

sequence_[printf | (title, director, year, [(name,rating)]) <- filmList] 

this will only handle those films in filmList having exactly one name and rating, silently ignoring everything else.

Finally, check out mapM_ and forM_: they are simpler than sequence_ + list comprehension. E.g.

foo :: IO ()
foo = forM_ [1..10] $ \i ->
         forM_ [1..i] $ \j ->
            print (i,j)

You probably need some nested loop as the one above: one for scanning the films, and one to scan the associated name/ratings.

Sign up to request clarification or add additional context in comments.

2 Comments

i have also another error now. Parse error in pattern: title Possibly caused by a missing 'do'? for this part after name,rating | title director year name rating <- filmList]
can you give me an example for how to use forM_ or mapM_for my program? because i'm not familiar with them.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.