If I just have a very simple custom data type:
data Person = Person {first_name :: String,
last_name :: String
} deriving (Ord, Eq, Show)
If I have a list of these Person data types, and I want to sort it by last_name if and only if the first_name is the same. But I should not sort the first_name. Simply call the following obviously doesn't work.
import Data.Function (on)
import Data.List (sortBy)
sortBy (compare `on` last_name ) persons
How can I solve it? I do agree it's quite confusing. What I want is that if I have the following (that's definitely not a list of the custom data type, I just want to show it clearly)
[("c","d"),("a","c"),("a","a")]
After sorting I would like to have
[("c","d"),("a","a"),("a","c")]
instead of
[("a","a"),("a","c"),("c","d")]
So the idea is that first element should still appear at first, since it does not have the same first_name with the other two. Is that possible? Thanks!
The comparison function you want is to treat two
Personvalues as equal if their first names are different. If the first names are the same, then compare based on the last name.Since
sortin Haskell is stable, if an elementaprecedes an equal elementbin the input, it will also precedebin the output. In this case, two elements with different first names will compare as equal, sosortwill really only sort the consecutive subsequences sharing a first name.There is probably a clever way to implement this, but a straightforward comparison function might look like
Given
people = [ Person "A" "B",Person "Z" "C",Person "Z" "A"], you can see the difference betweensortBy (comparing last_name)andsortBy foo.