将自定义排序应用于列表(以对列表列表进行排序)

时间:2012-03-08 04:27:25

标签: list sorting haskell

有一个示例说明如何在此页面上使用自定义排序对列表进行排序: 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]

标准小于订单让我比较列表,例如

[1,2,3] < [0,4,5]

是假的。但这不适用于上面的示例函数:

Main> xxx [1,2,6] [1,7,3]
ERROR - Cannot infer instance
*** Instance   : Integral [a]
*** Expression : xxx [1,2,6] [1,7,3]

是否有一种简单的方法可以将此类订单扩展到列表?

我想要这个功能的原因是使用sortBy使用我的自定义排序对列表列表进行排序。

我要感谢解决方案代码示例,有关阅读内容的建议,或介于两者之间的任何内容。我希望有一些内置的方法可以用语言来完成,而不是编写一个直接比较列表的函数。

2 个答案:

答案 0 :(得分:5)

您可以将比较函数转换为具有代码的列表的比较函数:

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

现在,您可以在两个列表中使用xxx

> compareList xxx [1,2,6] [1,7,3]
LT
> compareList xxx [2,2,6] [1,7,3]
GT

然后,您可以使用它来使用比较器对嵌套列表进行排序:

> sortBy (compareList xxx) [[2,2,6], [1,7,3], [1,1,1]]
[[1,7,3],[1,1,1],[2,2,6]]

答案 1 :(得分:1)

要复制<的行为,您必须使xxx函数成为类型类的一部分。这可能不值得。

相反,请考虑专门为列表编写新版xxx

xxxl :: Integral i => [i] -> [i] -> Ordering
xxx1 [] [] = EQ
xxxl [] _ = LT
xxxl _ [] = GT
xxxl (l1:_) (l2:_) | odd l1    = LT
                   | otherwise = GT

您可能希望以其他方式处理空列表。这也说明了为什么你不能自动将xxx函数推广到列表: 如何处理空列表?你必须以某种方式回答这个问题,为列表编写新函数是最简单的方法。

您现在可以将xxxl功能与sortBy一起使用来排序列表列表:sortBy xxx ...