2012-07-14 64 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