Kris Rice
Kris Rice

Reputation: 753

How do I filter a list in Haskell based on a particular elements value?

I have a list of type Film, where Film(Director Title Year Likes Dislikes), which corresponds to Film -> String -> String -> Int -> [String] -> [String]. I also have a function that takes in the likes and dislikes lists and returns a percentage rating, as such that:

rating :: Likes -> Dislikes -> Int
rating likes dislikes = (((length [likes]) / ((length [dislikes]) + (length [likes]))) * 100)

My problem: I cannot work out how to use filter to sort this list, to determine whether or not each film's rating is 75% or over.

This is my current attempt:

filterFilm :: Film -> Bool
filterFilm (Film t d y likes dislikes)
            | (rating likes dislikes) > 74  = True
            | otherwise                     = False

-- List film rating with and over 75%
listRating :: Database -> Database
listRating (x:xs) = filter (filterFilm x) (x:xs)

I get this error:

Cw 2018.hs:87:29: error:
    • Couldn't match expected type ‘Film -> Bool’
                  with actual type ‘Bool’
    • Possible cause: ‘filterFilm’ is applied to too many arguments
      In the first argument of ‘filter’, namely ‘(filterFilm x)’
      In the expression: filter (filterFilm x) (x : xs)
      In an equation for ‘listRating’:
          listRating (x : xs) = filter (filterFilm x) (x : xs)
   |
87 | listRating (x:xs) = filter (filterFilm x) (x:xs)    |        

Any suggestions? Thanks in advance!

Upvotes: 1

Views: 1044

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476503

I think you use filter the wrong way. filter is a function that takes two parameters, the first one a predicate a -> Bool and the second one a list of as.

Now the parameter that is passed to listRating is that list, so listRating l, and you thus call the filter with filter filterFilm l, so:

listRating :: Database -> Database
listRating l = filter filterFilm l

We can also remove the l parameter both in the head and body of the function, like:

listRating :: Database -> Database
listRating = filter filterFilm

Note that you can simplify your filterFilm function to:

filterFilm :: Film -> Bool
filterFilm (Film t d y likes dislikes) = rating likes dislikes > 74

Upvotes: 2

Related Questions