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.