2012-07-14 87 views
34

我想用一个属性,然后由另一排序(如果第一个属性是一样的。)组成两个比较函数?

什么在Haskell组成两个比较函数的惯用方式,即用sortBy使用的功能?

鉴于

f :: Ord a => a -> a -> Ordering 
g :: Ord a => a -> a -> Ordering 

组成fg会产生:

h x y = case v of 
      EQ -> g x y 
      otherwise -> v 
     where v = f x y 
+21

使用'Data.Monoid',你可以得到:'fxy \'mappend \'gxy'。 – Vitus 2012-07-14 18:50:37

回答

51

维斯特指出的MonoidOrdering非常酷的实例。如果需要用实例结合起来instance Monoid b => Monoid (a -> b)事实证明你的作文功能仅仅是(准备):

mappend 

检查出来:

Prelude Data.Monoid> let f a b = EQ 
Prelude Data.Monoid> let g a b = LT 
Prelude Data.Monoid> :t f `mappend` g 
f `mappend` g :: t -> t1 -> Ordering 
Prelude Data.Monoid> (f `mappend` g) undefined undefined 
LT 
Prelude Data.Monoid> let f a b = GT 
Prelude Data.Monoid> (f `mappend` g) undefined undefined 
GT 

+1功能强大且简单的抽象

+4

哇......真棒。 – huon 2012-07-14 23:57:13

+0

我知道Haskell必须有一个优雅的解决方案:)谢谢你这么清楚简洁地解释它。 – 2012-07-21 02:53:54

+0

这太棒了。要对一系列对进行排序:'sortBy(比较fst <>比较snd)' – dcastro 2017-01-20 16:22:12