correct • elegant • free

△ The $ Operator △

◅ The $ Rule

Esoteric uses for the $ operator ▻

The $ Rule revisited

Consider showsum0.hs.

showSum x y = show x ++ " + " ++ show y ++ " = " ++ show (x + y)

It would seem from our description of The $ Rule so far that we could eliminate the parentheses in show (x + y), as in showsum1.hs.

showSum x y = show x ++ " + " ++ show y ++ " = " ++ show $ x + y -- wrong!

But this results in a type error in " = " ++ show. The problem is that we've been focusing on what happens to the right of the $ operator, but it also affects what happens to its left. We could patch up The $ Rule, but it gets rather unwieldy.

The $ Rule Improved(?)

The $ operator acts as right parenthesis with an implied left parenthesis after the preceding $ operator -- if any, otherwise the beginning of the expression -- followed by a left parenthesis with an implied right parenthesis at the end of the expression.

Now we can see what went wrong in the previous example. Applying the new rule to this expression yields showsum2.hs, and it is clear why this is not doing what we wanted: the $ operator has grouped together everything to its left, as well as everything to its right.

showSum x y = (show x ++ " + " ++ show y ++ " = " ++ show) (x + y) -- wrong!

Our new version of The $ Rule is correct, but I find it unhelpfully complicated. Perhaps, now that we've got a feel for how the $ operator works in practice, we should revisit the theory.

The $ Operator, Really

We've been talking about the $ operator as though it were some kind of syntactic sugar, but in fact it's not special syntax at all. It's defined in the Prelude like this:

infixr 0 $
($) :: (a -> b) -> a -> b
f $ x = f x

The first line states that $ is a right associative operator with precedence 0. Right-associative means that a $ b $ c parses as a $ (b $ c). Precedence 0 is the lowest precedence, and means that, for any operators and , the expression a ⊕ b $ c ⊗ d parses as (a ⊕ b) $ (c ⊗ d).

The second line gives the type of the $ operator. It takes two arguments, the first argument is itself a function f, which can be of any type at all, so long as it has just one argument. The second argument to $ must be of f's input type. The return type of the overall expression is the same as the return type of f.

The third line defines what $ actually does: it applies its first (left) argument, the function f, to its second (right) argument.

It's the third line that caused me confusion: it seems to be saying that the $ operator doesn't do anything at all! Apparently, wherever we have f $ x, we can replace it with f x. And this is true, provided f and x are sufficiently simple. But when the expressions become more complicated - involving other operators or function application - the low precedence and right associativity of the $ operator, given by the first line of its definition, come into play.

Seen from the point of view of the $ operator, since it has the lowest possible precedence, any expression either to its left or to its right will be "gathered up" to form the operator's arguments. For exactly the same reason, 3 + 4 * 523 (and not 35) because the lower precedence + gathers up the entire expression 4 * 5. Generally, such gathering up is more useful to the right of the operator, and conveniently the $ operator is right-associative, so what it gathers up on its right will include any other $ operators.

I've realized that the various phrases used to describe precedence induce a slight cognitive dissonance in me. Compared to a lower precedence operator, a higher precedence operator binds more tightly; but this means that it gathers up less of the expression around it: the implied parentheses are smaller. The higher precedence operator is also lower in the parse tree (assuming the parse tree is drawn in the usual Computer Science way: with its root at the top of the page!).


That concludes what I have to say in explanation of the $ operator. A couple of clarifications and unusual cases follow, but my hope is that you now understand what the $ operator does and why. If not, I can only suggest that you go back and read through the material so far till you do! If understanding just won't come, please email me (link at the bottom of the page) and perhaps together we can work out how to improve this tutorial.

△ The $ Operator △

◅ The $ Rule

Esoteric uses for the $ operator ▻