Reputation: 63
There's an example of how to sort a list with a custom ordering at this page: http://zvon.org/other/haskell/Outputlist/sortBy_f.html
xxx a b | odd a = LT
| otherwise = GT
Input: sortBy xxx [1,2,3,4,5,6,7]
Output: [1,3,5,7,6,4,2]
The standard less than order lets me compare lists, e.g.
[1,2,3] < [0,4,5]
Is False. But this doesn't work with the above example function:
Main> xxx [1,2,6] [1,7,3]
ERROR - Cannot infer instance
*** Instance : Integral [a]
*** Expression : xxx [1,2,6] [1,7,3]
Is there an easy way to extend such an order to lists?
The reason I want this functionality is to use sortBy to sort lists of lists using my custom ordering.
I'd be grateful for example solution code, advice on what to read up on, or anything in between. I'm hoping there's some built-in way to do this with the language rather than write a function that compares the lists directly.
Upvotes: 4
Views: 2347
Reputation: 14678
You can convert a comparison function to a comparison function for lists with the code:
import Data.Monoid (mconcat)
compareList :: (a -> b -> Ordering) -> [a] -> [b] -> Ordering
compareList _ [] [] = EQ
compareList _ (_:_) [] = GT
compareList _ [] (_:_) = LT
compareList comparer (x:xs) (y:ys) =
comparer x y `mappend` compareList comparer xs ys
Now you can use xxx
on two lists:
> compareList xxx [1,2,6] [1,7,3]
LT
> compareList xxx [2,2,6] [1,7,3]
GT
You could then use that to sort nested lists using your comparer:
> sortBy (compareList xxx) [[2,2,6], [1,7,3], [1,1,1]]
[[1,7,3],[1,1,1],[2,2,6]]
Upvotes: 5
Reputation: 68172
To replicate the behavior of <
you would have to make your xxx
function part of a type class. This is probably not worth it.
Instead, consider writing a new version of xxx
specifically for lists:
xxxl :: Integral i => [i] -> [i] -> Ordering
xxx1 [] [] = EQ
xxxl [] _ = LT
xxxl _ [] = GT
xxxl (l1:_) (l2:_) | odd l1 = LT
| otherwise = GT
You might want to handle empty lists in some other fashion. This also illustrates why you cannot automatically generalize your xxx
function to lists: how would you handle empty lists? You have to answer this question somehow, and writing a new function for lists is the easiest way.
You can now use your xxxl
function with sortBy
to sorts lists of lists: sortBy xxx ...
.
Upvotes: 1