2012-07-14 11 views
34

Chciałbym sortować według jednej właściwości, a następnie przez innego (jeśli pierwsza nieruchomość jest taka sama).tworząc dwie funkcje porównania?

Jaka jest idiomatyczne sposób w Haskell komponowania dwie funkcje porównania, to znaczy funkcja używana z sortBy?

względu

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

tworzenia f i g że wydajność:

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

Używanie 'Data.Monoid', możesz uzyskać:' fxy \ 'mappend \' gxy'. – Vitus

Odpowiedz

51

wita wskazuje na bardzo chłodnego wystąpienie Monoid do Ordering. Jeśli połączyć to z instancji instance Monoid b => Monoid (a -> b) okazuje się czynność skład jest tylko (get ready):

mappend 

Sprawdź:

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 dla silnych i prostych abstrakcji

+4

Woah ... to jest niesamowite. – huon

+0

Wiedziałem, że Haskell musi mieć to eleganckie rozwiązanie :) Dziękuję za wyjaśnienie tego tak jasno i zwięźle. –

+0

To jest genialne. Aby posortować listę par: 'sortBy (porównując fst <> porównywanie snd)' – dcastro