Haskell function composition (.) and function application ($) idioms: correct use

I have been reading Real World Haskell, and I am nearing the end, but a matter of style has been niggling at me to do with the (.) and ($) operators.

When you write a function that is a composition of other functions you write it like:

f = g . h

But when you apply something to the end of those functions I write it like this:

k = a $ b $ c $ value

But the book would write it like this:

k = a . b . c $ value

Now, to me they look functionally equivalent, they do the exact same thing in my eyes. However, the more I look, the more I see people writing their functions in the manner that the book does: compose with (.) first and then only at the end use ($) to append a value to evaluate the lot (nobody does it with many dollar compositions).

Is there a reason for using the books way that is much better than using all ($) symbols? Or is there some best practice here that I am not getting? Or is it superfluous and I shouldn't be worrying about it at all?


Solution 1:

I guess I can answer this from authority.

Is there a reason for using the books way that is much better than using all ($) symbols?

There's no special reason. Bryan and I both prefer to reduce line noise. . is quieter than $. As a result, the book uses the f . g . h $ x syntax.

Solution 2:

They are indeed equivalent: Keep in mind that the $ operator does, essentially, nothing. f $ x evaluates to f x. The purpose of $ is its fixity behavior: right-associative and minimal precedence. Removing $ and using parentheses for grouping instead of infix precedence, the code snippets look like this:

k = a (b (c (value)))

and

k = (a . b . c) value

The reason for preferring the . version over the $ version is the same reason for preferring both over the very parenthesized version above: aesthetic appeal.

Although, some might wonder if using infix operators instead of parentheses is based on some subconscious urge to avoid any possible resemblance to Lisp (just kidding... I think?).

Solution 3:

I'd add that in f . g $ x, f . g is a meaningful syntactic unit.

Meanwhile, in f $ g $ x, f $ g is not a meaningful unit. A chain of $ is arguably more imperative -- first get the result of g of x, then do f to it, then do foo to it, then etc.

Meanwhile a chain of . is arguably more declarative, and in some sense closer to a dataflow centric view -- compose a series of functions, and ultimately apply them to something.

Solution 4:

For me, I think the answer is (a) the neatness, as Don said; and (b) I find that when I'm editing code, my function may end up in point-free style, and then all I have to do is delete the last $ instead of going back and changing everything. A minor point, certainly, but a nicety.

Solution 5:

There's an interesting discussion of this question on this haskell-cafe thread. Apparently there's a minority viewpoint that holds that the right associativity of $ is "just plain wrong", and choosing f . g . h $ x over f $ g $ h $ x is one way of side-stepping the issue.