The ``$`` Rule revisited
========================
Consider `showsum0.hs`_.
.. _showsum0.hs: http://static.tobold.org/dollar/showsum0.hs
.. include:: showsum0.hs
:literal:
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`_.
.. _showsum1.hs: http://static.tobold.org/dollar/showsum1.hs
.. include:: showsum1.hs
:literal:
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.
.. admonition:: 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.
.. _showsum2.hs: http://static.tobold.org/dollar/showsum2.hs
.. include:: showsum2.hs
:literal:
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 * 5`` ⇒ ``23`` (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!).
Interlude
---------
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.