One of the things I like about languages like Haskell and ML is how you can often figure out what a function does just by looking at its type. For example, I recently came across the `on`

function (defined in `Data.Function`

), which I had not encountered before. The example defines a function `groupOn`

like so:

```
groupOn :: Eq b =>; (a ->; b) ->; [a] ->; [[a]]
groupOn f = groupBy ((==) `on` f)
```

and then shows how it can be used

`groupOn isDigit "46a12b159c"`

which yields

`["46","a","12","b","159","c"]`

So hmm, this `on`

function seems pretty useful, but what does it do? To figure it out, just look at its type:

`on :: (b ->; b ->; c) ->; (a ->; b) ->; a ->; a ->; c`

That looks very similar to the type for function composition!

`(.) :: (b ->; c) ->; (a ->; b) ->; a ->; c`

From the types, it looks like `on`

might work just like function composition, except that the first argument is a binary (rather than unary) function. It turns out that this is exactly what `on`

does. Its definition is:

`f `on` g = \x y ->; f (g x) (g y)`

This simple function turns out to quite handy, especially if you favor a point-free style. Apparently the most common use for `on`

is in conjuction with the various "By" functions in `Data.List`

, where it is used to build predicates. For example:

`sortBy (compare `on` fst) [(5,'a'),(1,'b'),(3,'c')] == [(1,'b'),(3,'c'),(5,'a')]`

Useful stuff!