Search code examples
listhaskelltake

Haskell - How to take n items from a tuple list after sorting


Hi I am a beginner to haskell. I am trying to get the first 3 items from this tuple list:

[("and",2),("cat",1),("dog",1),("rabbit",1),("the",2)]

First I sort the list by frequency and descending order:

sortWords =  sortBy(flip compare `on` snd)

This gives me the result:

[("and",2),("the",2),("cat",1),("dog",1),("rabbit",1)]

Then I know I can do the function:

take 3 [("and",2),("the",2),("cat",1),("dog",1),("rabbit",1)] 

which gives me the desired result of [("and",2),("the",2),("cat",1)]

However, I want to be able to incorporate the take function into the sortWords function. The problem is, when I attempt to do this, for example:

sortWords =  take 3 (sortBy(flip compare `on` snd))

this does not work.

Ideally, I want to keep sortWords as the end function so I do not want to pass it into another to be able to perform the take function. If there's a way to perform take before calling sortWords that could be a solution, however I have also tried this and found that the words which are taken are not sorted first and therefore do not give me the result I want.

Thank you


Solution

  • The problem here is that sortBy (flip compare `on` snd) is not a list of tuples, it is a function that takes as input a list of tuples and returns a list of tuples.

    We can use the function composition operator (.) :: (b -> c) -> (a -> b) -> a -> c:

    sortWords :: Ord b => [(a,b)] -> [(a,b)]
    sortWords = take 3 . sortBy (flip compare `on` snd)
    

    here we thus first will apply sortBy (flip compare `on` snd) on the input, and then we will apply take 3 on the output of that function.