The ``$`` Rule
==============

In the past, I was confused by the ``$`` operator. It would sometimes
appear in other people's programs (never my own, of course, since I
didn't understand it), and seemed to be doing something quite
magical. Then I devised The ``$`` Rule.

.. admonition:: The ``$`` Rule

    The ``$`` operator acts as a left parenthesis with an implied
    right parenthesis at the end of the expression.

That's it. Nothing magical at all. It's just an alternative to using
parentheses for grouping.

(As I later discovered, The ``$`` Rule doesn't quite tell the whole
story. We will get to that story before the end of this tutorial. But
The ``$`` Rule covers the vast majority of uses of the ``$`` operator,
so it's a good rule of thumb if you're as puzzled as I was.)

Examples
--------

Let's look at some examples of the ``$`` operator and The ``$`` Rule
in practice. Suppose we need a function which will extract a bare file
name from a FilePath, and fold it to lower case. We want to write
``filefold :: FilePath -> String``, so that e.g. ``filefold
"/etc/README"`` ⇒ ``"readme"``. Here's our first version,
`filefold0.hs`_.

.. _filefold0.hs: /software/download/dollar/filefold0.hs
.. include:: filefold0.hs
    :literal:

Maybe this looks a bit cluttery with all those parentheses, so let's
see if the ``$`` operator can help us. At the end of the expression
are 3 right parentheses: we can eliminate them by replacing each
corresponding left parenthesis with a ``$`` operator. This yields
`filefold7.hs`_.

.. _filefold7.hs: /software/download/dollar/filefold7.hs
.. include:: filefold7.hs
    :literal:

Note that we cannot eliminate the parentheses in ``('/' /=)``. In
terms of The ``$`` Rule, this is because the right parenthesis is not
at the end of the expression. (More accurately, the parentheses here
are a special syntax that creates a section, and are not just for
grouping.)

It's a matter of taste whether you prefer ``filefold0`` or
``filefold7``: they are exactly equivalent. In this case, I personally
don't think the ``$`` operator does anything to improve
clarity. Perhaps we were too greedy: for fewer dollars we can get
`filefold4.hs`_, which emphasizes that the transformation takes place
in two parts (one of which involves several functions).

.. _filefold4.hs: /software/download/dollar/filefold4.hs
.. include:: filefold4.hs
    :literal:

Altogether, for these 3 nested functions there are 8 ways to split up
the work between dollars and parentheses. All are illustrated in
`filefolds.hs`_. I think the clearest are ``filefold0`` and
``filefold4``; their duals - ``filefold7`` and ``filefold3``
respectively - also have something to commend them. The remainder are
perverse.

.. _filefolds.hs: /software/download/dollar/filefolds.hs
.. include:: filefolds.hs
    :literal:

Of course, there are yet more ways to skin this cat. We can emphasize
the two parts of the transformation even further by introducing a new
name, as in `filefoldn.hs`_.

.. _filefoldn.hs: /software/download/dollar/filefoldn.hs
.. include:: filefoldn.hs
    :literal:

Or we could use function composition to eliminate all names (and ``$``
operators), as in `filefold.hs`_. This is the least cluttered version
of all, and would, I think, be chosen by most seasoned Haskell
programmers. It's definitely not the *first* version I'd devise,
though!

.. _filefold.hs: /software/download/dollar/filefold.hs
.. include:: filefold.hs
    :literal:

More Examples
-------------

Back to the ``$`` operator. The judicious use of the ``$`` operator to
separate semantically distinct parts of a complex expression (as in
``filefold4``) seems promising. Consider ``putStr`` and friends, which
take a string argument. Except in the simplest cases, the argument
must be surrounded by parentheses, as in `calc0.hs`_.

.. _calc0.hs: /software/download/dollar/calc0.hs
.. include:: calc0.hs
    :literal:

A small but definite improvement is to use the ``$`` operator to
eliminate the parentheses around the argument to ``putStrLn``. This
gives us `calc1.hs`_.

.. _calc1.hs: /software/download/dollar/calc1.hs
.. include:: calc1.hs
    :literal:

The more complicated the expression, the more compelling the use of
the ``$`` operator. There are certain functions that take an IO action
as an argument, for example ``when`` (and ``unless``). An IO action
might be as simple as a call to ``putStrLn``::

    when debug (putStrLn "initialization started")
    initialize
    when debug $ putStrLn "initialization completed"

For a simple case like this, there's not much to choose between
parentheses and the ``$`` operator. But an IO action could equally
well be a multiline ``do`` expression::

    when debug $ do
        h <- openFile "debug.out" appendMode
        hPutStrLn h "dump of parse tree"
        hPutStr h (show parseTree)
        hClose h

Now the ``$`` operator is in its element: we *could* simply surround
the entire ``do`` expression in parentheses, but it is much neater to
avoid a "dangling" right-paren on the last line. This style is common
also in GUI programming: here is an example from the ``gtk2hs``
package::

  renderWithDrawable win $ do
    scale (realToFrac width'  / realToFrac width)
          (realToFrac height' / realToFrac height)
    svgRender svg

Another idiomatic use of the ``$`` operator is in constructors. Rather
than ``Just (x + y)``, we can write ``Just $ x + y``.

