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

getUserRatings :: String -&gt; [Film] -&gt; [(String,Int)]
getUserRatings search database = [(title,rate) | (Film title _ _ ratings) &lt;- database, (user,rate) &lt;- 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.
Using high-order functions is not much readable:

userRatings search = concatMap (\film -&gt;
  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} &lt;- database
    , (user,rate) &lt;- 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.