Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Ord comparing, but returns the smallest one

I compare list's length and then size of the first element, this way:

(maximumBy (comparing length <> comparing head)) sx

This code returns longest list and if there are multiple that are same length it will return the one that has biggest first element.

Is there an easy way to modify this to return second comparison to return the one that has the smallest first element?

like image 435
Blue Avatar asked Dec 07 '20 16:12

Blue


2 Answers

You can make use of Down which reverses the order of comparing:

import Data.Ord(Down(Down))

(maximumBy (comparing length <> comparing (Down . head))) sx

or you can flip the two operands when you are comparing the value:

(maximumBy (comparing length <> flip (comparing head))) sx

That being said, you should be careful with comparing head. Empty lists have no head, so that can result in an error if you are comparing two empty lists.

You can, like @DanielWagner says, make use of take 1. This works because lists [a] are an instance of Ord as well, given a is an instance of Ord. In that case the lists are ordered lexicographically. For lists with one or more elements, this thus means that we order by the first element:

maximumBy (comparing length <> flip (comparing (take 1))) sx
like image 189
Willem Van Onsem Avatar answered Dec 31 '22 06:12

Willem Van Onsem


This is why the Down newtype exists: to reverse ordering. Use it like this:

import Data.Ord

(maximumBy (comparing length <> comparing (Down . head))) sx
like image 21
Joseph Sible-Reinstate Monica Avatar answered Dec 31 '22 08:12

Joseph Sible-Reinstate Monica