dollar sign

The dollar sign, `\$`, is a controversial little Haskell operator. Semantically, it doesn’t mean much, and its type signature doesn’t give you a hint of why it should be used as often as it is. It is best understood not via its type but via its precedence. We believe it is the relative semantic emptiness of this operator combined with the relative obscurity of precedence that makes it so confusing at first glance.

Function application

The `\$` operator is an infix operator for … function application?

``(\$) :: (a -> b) -> a -> b``

Given an `a -> b` function and an `a` to apply it to, it gives us a `b`.

``````λ> sort \$ "julie"
"eijlu"``````

Weird infix, but okay. Haskell doesn’t need an operator for function application; white space is enough.

``````f :: a -> b
x :: a

f \$ x = f x``````
``````λ> sort "julie"
"eijlu"``````

This seems utterly pointless, until you look beyond the type.Here and throughout this article, we have simplified the type from what you may see if you query this information in your own REPL. The extra bits of information the REPL may give are not important to understanding this, so we’ve ignored them.

``````λ> :info (\$)
(\$) :: (a -> b) -> a -> b
-- Defined in ‘GHC.Base’
infixr 0 \$``````

This little note, so easily overlooked, at the end holds the key to understanding the ubiquity of `(\$)`: `infixr 0`.

• `infixr` tells us it’s an infix operator with right associativity.
• `0` tells us it has the lowest precedence possible.

In contrast, normal function application (via white space)

• is left associative and
• has the highest precedence possible (10).

So the role of the `\$` operator is to give us function application with a different – opposite, really – associativity and precedence.

What that means is that you usually see the `\$` where standard function application wouldn’t have the necessary associativity and precedence for the context. And what that means is you usually see it used instead of parentheses to associate things that otherwise wouldn’t.

That will be more clear with some examples. Compare:

``````λ> sort "julie" ++ "moronuki"
"eijlumoronuki"

λ> sort \$ "julie" ++ "moronuki"
"eiijklmnooruu"``````

In the first case, the application of `sort` to “julie” is binding the tightest, so the argument to `sort` is just the first string, “julie”, and the sorted string “eijlu” is the first argument to `(++)`. In the second case, using `\$` changes the associativity, exactly as if we’d used parentheses:

``````λ> sort ("julie" ++ "moronuki")
"eiijklmnooruu"``````

So the argument to `sort` is the concatenated two strings, instead of only “julie”.

Composition

One pattern where you see the dollar sign used sometimes is between a chain of composed functions and an argument being passed to (the first of) those.

``````λ> head . sort \$ "julie"
'e'``````

This is a bit odd since we just said the `\$` is right associative; there’s really nothing to evaluate on the right. So, the key here is the precedence. We can’t do this:

``λ> head . sort "julie"``

It wouldn’t evaluate properly because

• the `(.)` operator has a precedence of 9, but
• function application (`sort "julie"`) has higher precedence.

That means the application of `sort` to its argument would happen before the composition of `head` and `sort`. The `(.)` expects two function arguments:

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

But applying `sort` to an argument means it’s not a function anymore.

``````λ> :type (sort "julie")
(sort "julie") :: [Char]``````

The second argument to `(.)` can be `sort`, but it cannot be `sort "julie"`; `sort` is an `a -> b` function but `sort "julie"` is not.

But, weirdly, this isn’t the only way `\$` can be used with regard to function composition. In some cases `\$` can replace the composition operator, `(.)`. So, both of these are valid Haskell:

``````λ> head . sort \$ "julie"
'e'

'e'``````

In the first case, it’s the 0-precedence of `\$` that matters most; in the second case, it’s the right-associativity that matters. In the second case, everything on the right gets evaluated first, and then `head` applies to that result. So in this case we end up with the same result either way.

However, they cannot always be used interchangeably. These are both fine:

``````λ> headSort xs = head \$ sort xs

'e'

'e'``````

But this is not:

``λ> headSort = head \$ sort``

In this case, for once, it’s because of the type, not because of the precedence. `sort` by itself is not the right type of thing to be the second argument to `\$`.

Large args

There are times when the dollar sign is used before a particularly large argument to a function. This is most common, perhaps, with `do` blocks, but also shows up at times when there is a biggish anonymous function being passed as an argument to another function. Let’s look at a really typical example; this is from the documentation for the `scotty` web framework.

``````{-# LANGUAGE OverloadedStrings #-}
import Web.Scotty

import Data.Monoid (mconcat)

main = scotty 3000 \$
get "/:word" \$
do
beam <- param "word"
html \$ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]``````

We’ve rearranged the layout a tiny bit to better match our Type Classes `do`-block aesthetics, but that’s otherwise straight from the docs. This short snippet has two `\$` operators. Both `scotty` and `get` each need some big action as their second argument, so the right-associativity of `\$` allows the whole big chunk after it to act as a single argument to the function. You could substitute parentheses for the exact same effect.

``````{-# LANGUAGE OverloadedStrings #-}
import Web.Scotty

import Data.Monoid (mconcat)

main = scotty 3000
(get "/:word"
(do
beam <- param "word"
html \$ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"]))``````

But typically Haskellers do not prefer to wrap such big chunks in parentheses.

Starting with GHC 8.6.1, there is also a language extension called `BlockArguments` that can, if enabled, make the `\$` operator unnecessary in many of these contexts.

``````{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE BlockArguments #-}
import Web.Scotty

import Data.Monoid (mconcat)

main = scotty 3000
(get "/:word"
do
beam <- param "word"
html \$ mconcat ["<h1>Scotty, ", beam, " me up!</h1>"])``````

This is the same as the first two snippets. You may notice you need to keep the parentheses (or use `\$`) around the block that starts with `get` because `get` isn’t one of the keywords that works with `BlockArguments`.

And a curiosity

Finally, we will note a curiosity about `\$`. Its type

``(\$) :: (a -> b) -> a -> b``

can also be written

``(\$) :: (a -> b) -> (a -> b)``

In fact, that is how the type should be read and understood, but because Haskell is curried by default, the second set of parentheses is unnecessary and, therefore, not usually written. But that means `\$` is just an identity function for … functions.

``````id :: a -> a

-- a ~ (a -> b)

id @(_ -> _) :: (a -> b) -> (a -> b)``````

That means, if you wanted, you could sometimes substitute the `id` function for `\$`.The backticks around `id` allow it to be used in infix position; putting backticks around normal prefix functions enables you to use them as infix functions, if you like.

``````λ> head \$ sort "julie"
'e'

'e'``````

Of course, if you are infixing `id` you could be prefixing it, right?

``````λ> id head (sort "julie")
'e'``````

And that is just the same as this:

``````λ> head (sort "julie")
'e'``````

You cannot, of course, do this in all the contexts you see `\$` used in, because infix `id` and `\$` don’t have the same…you guessed it, associativity and precedence.When you make a prefix function, such as `id` infix by backticking it but don’t otherwise specify the associativity and precedence for its infix use, it defaults to left-associativity and a precedence of 9, making it the same precedence as function composition but lower (by one) than normal prefix function application. You can substitute infix `id` for the dollar signs in the `scotty` examples, but you need to add some parentheses as well. We will leave understanding exactly where and why as an exercise for the reader.

While this little curiosity about the relationship of `\$` and `id` is interesting, please do not start writing Haskell with a lot of infix `id`. It will lead you to bad places and make your coworkers hate you.

Join Type Classes for courses and projects to get you started and make you an expert in FP with Haskell.