141

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?

nbro
  • 15,395
  • 32
  • 113
  • 196
Robert Massaioli
  • 13,379
  • 7
  • 57
  • 73
  • 4
    Note that the second example can be done as `k = a $ b $ c value` – Thomas Eding Jun 13 '10 at 17:11
  • 1
    Yes it can, as Zifre mentioned below, but I decided to leave it there as it does not harm anything and makes his (and now your) comments make sense. Thankyou though. +1 :) – Robert Massaioli Jun 14 '10 at 01:44
  • 2
    Another common approach is `a . b $ c value`, which I don't like quite as much as the third example but saves a few characters. – John L Jun 20 '12 at 10:31
  • Regarding performance: https://stackoverflow.com/questions/47132554/haskell-performance-composition-vs-application – Peter Becich Jul 27 '21 at 00:33

7 Answers7

162

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.

nbro
  • 15,395
  • 32
  • 113
  • 196
Don Stewart
  • 137,316
  • 36
  • 365
  • 468
  • 4
    Well, I cannot hope for a better answer than this one; from one of the authors himself. :) And that makes sense, it does look much quieter on the page as I read. Marking this as the answer because It directly answers the question. Thankyou for the response; and, infact, the book. – Robert Massaioli Jun 13 '10 at 03:16
  • 43
    Not to disagree with the author, but I think there is another more prominent reason in the mental model of *creating* something rather than *using* it. Haskell users tend to want to think of `f.g.h` as a new clever creation rather `f(g(h()))`. Now they're calling a new, albeit anonymous, function which they created rather than just chaining a big dictionary of prefabbed function calls like a PHP user. – Evan Carroll Jun 22 '10 at 15:20
  • 3
    That's an interesting statement: 'reduce line noise' and 'quieter than'. I never thought about programming languages in this terminology, but it makes perfect sense. – Rabarberski May 27 '13 at 19:33
57

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?).

C. A. McCann
  • 76,893
  • 19
  • 209
  • 302
45

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.

nbro
  • 15,395
  • 32
  • 113
  • 196
sclv
  • 38,665
  • 7
  • 99
  • 204
  • 2
    I'm learning Haskell (haven't coded anything meaningful) but I like to think of $ as a sort of "pipe" operator. Its a lot like the terminal | pipe (except the data flows right-to-left), but like terminal processes each unit is explicitly independent. – LostSalad Jun 23 '14 at 21:51
  • 1
    The `$` operator seems to behave similarly to the `<|` operator in F#. I believe both are defined the same, in fact - in F#, `(<|) a b = a b` and in Haskell, `a $ b = a b`, which are essentially equivalent. – Tom Galvin Mar 17 '15 at 18:55
  • @Quackmatic Fairly certain it's `(<|) b a = a b` in F#, since it's used like `[1; 2; 3; 4; 5] <| List.map ((+) 1)`, if memory serves. – Joshua Grosso Reinstate CMs Feb 19 '16 at 22:13
  • @BalinKingOfMoria The `<|` operator passes the value to the function, rather than passing the function to the value - your code example would work with the `|>` operator, instead. – Tom Galvin Feb 22 '16 at 00:32
  • @Quackmatic Oh. Wasn't aware there were multiple versions (I haven't used F# very much). – Joshua Grosso Reinstate CMs Feb 22 '16 at 15:49
  • Excellent distinction, you expressed what I had as a gut feeling. – ThomasH Aug 16 '16 at 20:20
20

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.

Community
  • 1
  • 1
Antal Spector-Zabusky
  • 36,191
  • 7
  • 77
  • 140
  • Yeah that is a good reason to write it like that, if you want to end in a function composition then it is faster. :) Yay for saving keystrokes, but more importantly time. +1 – Robert Massaioli Jun 13 '10 at 08:22
14

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.

Travis Brown
  • 138,631
  • 12
  • 375
  • 680
3

It's just a matter of style. However, the way the book does it makes more sense to me. It composes all the functions, and then applies it to the value.

Your method just looks strange, and the last $ is unnecessary.

However, it really doesn't matter. In Haskell, there are usually many, many, correct ways to do the same thing.

Zifre
  • 26,504
  • 11
  • 85
  • 105
  • 3
    I didn't notice that the last $ was unnecessary but I should have. Thanks and I'll leave it there so that people know what this comment means. – Robert Massaioli Jun 13 '10 at 08:21
0

I realize this is a very old question, but I think there is another reason for this that hasn't been mentioned.

If you are declaring a new point-free function f . g . h, the value you pass in will be automatically be applied. However, if you write f $ g $ h, it will not work.

I think the reason the author prefers the composition method is because it leads to a good practice of building up functions.

dkasak
  • 2,651
  • 17
  • 26
hackeryarn
  • 302
  • 3
  • 10