(o1, o2) -> o1 - o2 なんて呪文はもうやめて! - Java8でのComparatorの使い方 http://qiita.com/tag1216/items/50ecf6a7bc10218ee889 という記事でthenComparingによる複合ソートが紹介されていたが、これはHaskellだと a→a→Ordering 上のMonoid演算による結合だな。
JavaのComparator<T>に相当するのはHaskellでは a→a→Ordering という関数型だが、OrderingはMonoidであり、また b がMonoidであるとき a→b もMonoidなので、a→a→Ordering もMonoidとなり、Monoidの演算で結合できる。以下の例は、タプルを第二要素、第一要素の順で比較する場合。
import Data.Monoid
import Data.Ord
cmp :: (Ord a, Ord b) => (a,b) -> (a,b) -> Ordering
cmp = comparing snd <> comparing fst
ちなみに、逆順のComparator<T>を作るためにreversedというメソッドを使っていたが、これはHaskellでは単純に a→a→Ordering の引数の順番をflipで入れ替えてやれば良い。以下は第二要素の比較を逆順で行う場合。
cmp2 :: (Ord a, Ord b) => (a,b) -> (a,b) -> Ordering
cmp2 = flip (comparing snd) <> comparing fst