2012-07-14 12 views
34

Vorrei ordinare per una proprietà e poi da un altro (se la prima proprietà è la stessa.)che compone due funzioni di confronto?

Nei il modo idiomatica in Haskell di comporre due funzioni di confronto, cioè una funzione utilizzata con sortBy?

Dato

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

composizione f e g sarebbe resa:

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

Utilizzando 'Data.Monoid', puoi ottenere:' fxy \ 'mappend \' gxy'. – Vitus

risposta

51

vitus sottolinea l'istanza molto fresco di Monoid per Ordering. Se si combinano con l'istanza instance Monoid b => Monoid (a -> b) si scopre la funzione di composizione è solo (prepariamoci):

mappend 

Check it out:

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 per astrazioni potenti e semplici

+4

Woah ... è fantastico. – huon

+0

Sapevo che Haskell doveva avere una soluzione elegante a questo :) Grazie per averlo spiegato in modo così chiaro e conciso. –

+0

Questo è geniale. Per ordinare una lista di coppie: 'sortBy (confrontando prima <> confronto snd)' – dcastro