One of the minor annoyances of prefix notation for function call is that it gets the order of operations backwards. When you compose several functions into an expression, you generally have to write the last step first:
(handle-message (decrypt (receive socket) key))
If you explained this to a computer the same way you explain it to a human, you'd probably write the steps in the order they're performed. If you're used to Unix pipelines, you might write it like this:
receive socket | decrypt _ key | handle-message
In a language with user-defined infix operators, it's easy to support exactly this. You can define a
| operator which simply applies its right argument to its left — the same as Haskell's
$, but with the arguments reversed. It looks and feels very like the Unix
|: it connects the output of one expression to the input of the next. The channels used are return value and arguments rather than stdout and stdin, but the effect is the same.
I can't remember where, but I think I've heard this operator suggested before for Haskell — presumably with a different name, since
| is taken. (Edit 16 Feb 2011: here, at least, and also
|> in F#.) Ignoring that inconvenient detail, its Haskell definition is simple:
infixl 0 | (|) :: a → (a → b) → b x | f = f x-- Or, to make the similarity to
(|) = flip ($)
$, this is a contemptibly trivial operator. All it does is apply one argument to the other, which doesn't sound like it could possibly be worth spending an infix operator on. But I find myself using it constantly in pseudocode, because it lets me write operations in the right order. It doesn't make code shorter, but it significantly reduces the distance between the code I write and the representation in my head. That's important enough to be worth a one-character infix operator.
Like any high-order operator,
| is much more useful when you have a terse way to write simple functions. Usually this means partial application, either in the form of currying, or an explicit partial application operator, or
op, or implicit
op (as in the example above). Combinators are nice by themselves, but they need partial application to be really useful.