2
\$\begingroup\$

The function returns a list of tuples which is generated through list comprehension:

getUserRatings :: String -> [Film] -> [(String,Int)]
getUserRatings search database = [(title,rate) | (Film title _ _ ratings) <- database, (user,rate) <- ratings, search == user]

Film is defined as:

type Rating = (String, Int)
data Film = Film {  title,director :: String,
                    year :: Int,
                    ratings :: [Rating] } deriving (Read,Show)

such that a database is:

testDatabase :: [Film]
testDatabase = [(Film "Blade Runner" "Ridley Scott" 1982 [("Amy",5),("Bill",8),("Ian",7),("Kevin",9),("Emma",4),("Sam",7),("Megan",4)])]

The function getUserRatings takes in a the users name and the database, searches the ratings in the database, then compiles the the tuple so that its in the format of:

film name (String), user rating (Int)

How might I write this more efficiently using higher order functions? I've attempted a few times but to no success using filters and maps; I don't know whether to post those attempts here or not. So I won't until advised otherwise.

\$\endgroup\$
2
  • \$\begingroup\$ "How might I write this more efficiently using higher order functions?" More efficiently or more readable? Your current version isn't that much different from concatMap + filter + map. \$\endgroup\$
    – Zeta
    Feb 23, 2016 at 21:03
  • \$\begingroup\$ @Zeta readable is probably better in my case. Thanks for the idea! \$\endgroup\$ Feb 23, 2016 at 22:18

1 Answer 1

1
\$\begingroup\$

Using high-order functions is not much readable:

userRatings search = concatMap (\film ->
  map ((title film,) . snd)
    $ filter ((==search) . fst) $ ratings film)

You need {-# LANGUAGE TupleSections #-} to be able to write (title film,).

Another useful extension is NamedFieldPuns.

getUserRatings search database
  = [ (title,rate)
    | Film{title, ratings} <- database
    , (user,rate) <- ratings
    , search == user
    ]

Writing Film{title, ratings} instead of Film title _ _ ratings is not only a bit shorter, it also allows you to change/reorder fields in Film without updating getUserRatings.

Btw, in my opinion, splitting getUserRatings in several lines adds more readability than rewriting it somehow.

\$\endgroup\$

Your Answer

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

Not the answer you're looking for? Browse other questions tagged or ask your own question.