Max
Max

Reputation: 81

Use of Proper printF command in IO Haskell

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

Upvotes: 0

Views: 115

Answers (1)

chi
chi

Reputation: 116174

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.

Upvotes: 3

Related Questions