Jameson Braga
Jameson Braga

Reputation: 41

A function of tuple of lists

I am sorry if this question is very trivial, but I have struggled to find an answer to it for quite a time, that is why I decided to post it here.

I want to build a function which takes a list of binary tuples: [(Integer, Integer)] and outputs the maximum Integer from all the second Integers from all tuples. I wrote the following code:

maxSecond:: [(Integer,Integer)] -> Integer
maxSecond [(ks, as)] = aux (unzip [(ks, as)])
  where aux ([ks],[as]) = maximum ([as])

But it only works if I input a list of only 1 tuple and outputs "Non-exhaustive patterns in function" error for a list of more than 2 tuples. My question is not as much how to actually solve the original problem, as why such an approach doesn't work in Haskell?

I have also wrote the following function:

aaa:: ([Integer], [Integer]) -> Integer
aaa ([as],[ms]) = 10

And apparently it is impossible to input a tuple of lists in Haskell (unless the lists are not made of 1 element). Is there any explanation to this?

Thank you!!

Upvotes: 4

Views: 316

Answers (1)

willeM_ Van Onsem
willeM_ Van Onsem

Reputation: 476567

A common mistake that beginner Haskell programmers make is that they think that [x] is a pattern that matches a list of any length. But [x] is in fact a pattern that matches a singleton list (a list with exactly one element, and that element is "linked" to x).

If we want to be able to process empty lists ([]) or non-empty lists (with a length larger than zero), we can just write as pattern x, x will than get "linked" to that list itself. Note that we can use any identifier we want. Pattern matching for lists is of course useful: for example to handle the case of an empty list, a cons, a list containing exactly one, two, three, five, etc. elements. But here we will only restrict ourselves, and make things more complicated.

In order to calculate the maximum of the second item of the tuples, we can process it by first making a mapping that generates a list of elements, each the second item of the corresponding tuple, and then we can calculate the maximum of that list, like:

maxSecond :: Ord a => [(a, a)] -> a
maxSecond xs = maximum (map snd xs)

We here thus make use of the map :: (a -> b) -> [a] -> [b] function to apply a function to all elements in the list xs, that function is snd :: (c, d) -> d that thus takes the second element of a 2-tuple, and then we calculate the maximum :: Ord e => [e] -> e to obtain the maximum of that list.

We can also use the (.) :: (b -> c) -> (a -> b) -> a -> c operator, and write it like:

maxSecond :: Ord a => [(a, a)] -> a
maxSecond = maximum . map snd

Upvotes: 6

Related Questions