Haskell: sortBy wrapped_f, sortBy (comparing f), and sortBy (compare `on` f)
Sunday, 28th June, 2009
Here are three version of sortByLength:
import Data.List --  longer :: [a] -> [a] -> Ordering longer a b = compare (length a) (length b) sortByLength0 :: [[a]] -> [[a]] sortByLength0 a = sortBy longer a --  import Data.Ord sortByLength1 = sortBy (comparing length) --  import Data.Function sortByLength = sortBy (compare `on` length)
As discussed in my previous post, the first was my answer to the exercise in Real World Haskell, the second is from comment 5 by Yair, the third is based on comment 8 by David. Thank you Yair and David for these suggestions.
The three versions are equivalent (although I admit I haven’t tested them for speed). With particular relevance to my previous post, none of these use decorate-sort-undecorate.  and  are clearly better than  as they obviate the need for the wrapper function
longer.  is my favourite for its readability.
Another thing worth noting is that  and  omit the parameter
a from the definition.
`on` are new to me, so I’ll outline them briefly here.
comparing is in Data.Ord:
comparing :: Ord a => (b -> a) -> b -> b -> Ordering comparing p x y = compare (p x) (p y)
longer a b is equivalent to
comparing length a b.
Using backticks around a function allows us to use the function as an infix rather than a prefix (see rwh ch 4, section Infix functions p 76), so the following are exactly equivalent:
(compare `on` length) (on compare length)
on is from Data.Function:
on :: (b -> b -> c) -> (a -> b) -> a -> a -> c (*) `on` f = \x y -> f x * f y
I can understand the type signature, and I can see how
on compare length a b would fit, but I’m afraid the definition is opaque. I might be able to come back to it after I’ve written about
&&&. Otherwise, I shall spend some time with my eyes open for different usages of
on in the wild. It was very difficult finding information on
on (many thanks to a contact on haskell-beginners who pointed me to Hoogle), so I think it will be worth writing up when I can.
It took the omission of parameters from  and  for me to realise that perhaps the thing about Haskell is how much it facilitates combining and mixing functions in different ways. Duh.