Finding the maximum item in the tuple list

I am a complete newbie to Haskell. I have a list of tuples that I use in Haskell: the structure is like this [(a,b),(c,d),(e,f),(g,h)]

I want to return the maximum element in this tuple according to the second value: Therefore, if the list of tuples is [(4,8),(9,10),(15,16),(10,4)] , I want the maximum the element was (15,16) .

But I have no idea how to do this. This is my attempt so far,

 maximum' :: (Ord a) => (Num a) => [(a,b)] -> a maximum' [] = error "maximum of empty list" maximum' [(x,y)] = -1 maximum' (x:xs) | snd x > snd(xs !! maxTail) = 0 | otherwise = maxTail where maxTail = maximum' xs + 1 

And I get this error message that doesn't make any sense to me:

 newjo.hs:23:25: Could not deduce (a ~ Int) from the context (Ord a, Num a) bound by the type signature for maximum' :: (Ord a, Num a) => [(a, b)] -> a at newjo.hs:19:14-47 `a' is a rigid type variable bound by the type signature for maximum' :: (Ord a, Num a) => [(a, b)] -> a at newjo.hs:19:14 In the second argument of `(!!)', namely `maxTail' In the first argument of `snd', namely `(xs !! maxTail)' In the second argument of `(>)', namely `snd (xs !! maxTail)'` 

I need help on how to do this.

+4
source share
4 answers

The solutions presented so far have been very elegant, and you should probably use them in any real code that you write. But here is a version that uses the same pattern matching style that you use.

 maximum' :: Ord a => [(t, a)] -> (t, a) maximum' [] = error "maximum of empty list" maximum' (x:xs) = maxTail x xs where maxTail currentMax [] = currentMax maxTail (m, n) (p:ps) | n < (snd p) = maxTail p ps | otherwise = maxTail (m, n) ps 

This solution avoids juggling indices around, and instead just keeps track of the current maximum element that returns when the entire list is passed. Generally, avoiding list indexes is considered good practice.

+4
source

An idiomatic way would be to use maximumBy (comparing snd) .

The message a ~ Int means that for some reason, Haskell indicates that a must be Int , but the type signature does not limit it to Int s. As Amos notes in the comments , and the GHC tells you the source location because you use it as the second argument !! which is Int .

+20
source

The idiomatic way to use libraries is to use maximumBy .

 maximumBy :: (a -> a -> Ordering) -> [a] -> a 

Then it remains only to define a function of the type a -> a -> Ordering so that it knows how to arrange the elements. The usual way to create Ordering objects is to use

 compare :: (Ord a) => a -> a -> Ordering 
+8
source

It's also worth noting that tuples in Haskell are instances of Ord . Thus, they can be ordered and compared. They are ordered using lexicographic ordering (primary by the first element of the tuple, secondary by the second, etc.). Therefore, the following is true:

 maximum [(1,1),(1,8),(2,1),(2,6)] == (2,6) 

If you want to get a tuple with a maximum second element. You can simply swap the tuple elements for the maximum function, and then swap the result elements as follows:

 maximum' :: (Ord a, Ord b) => [(a,b)] -> (a,b) maximum' l = swap $ maximum $ map swap l where swap (x, y) = (y, x) 

Although for this to work, both elements of the tuple must be instances of Ord .

+1
source

Source: https://habr.com/ru/post/1495875/


All Articles