5 ms·
Consider that, in Haskell: 1. all functions take a single argument (i.e., are curried) 2. function application is left-associative So "a b c d" is just apply
by epidemian 12y ago
Consider that, in Haskell:
1. all functions take a single argument (i.e., are curried)
2. function application is left-associative
So "a b c d" is just applying the function "a b c" with the argument "d", the same as "(a b c) d". "a b c" is the application of "c" to the function "a b", which, in turn, is the application of "b" to "a". So "a b c d" is the same as "((a b) c) d".
I personally find using the space symbol for a core concept of the language (function application) very elegant, and not dissimilar to other languages that strive to have simple and consistent syntax, like Smalltalk, where "obj meth1 meth2 meth3" is the same as "((obj meth1) meth2) meth3", even though Haskell and Smalltalk might be as different as programming languages can get :)
- tormeh 12y agoHow does currying help? You still have to figure out which argument belongs to which function. GHC demands parentheses if you try to write A(B(C(D))) as A B C D, so I'm pretty sure I'm right.
- tomp 12y agoNo, you're wrong. `A(B(C(D)))` is different from `(((A B) C) D)` (which is the parenthesized version of `A B C D`). Currying allows simple partial application; if A is a function that "takes 3 arguments" (i.e. it has type `w -> x -> y -> z`, which means that it takes an argument of type `w` and returns a function with type `x -> y -> z`, which takes an argument ...), you can say e.g. A_ = A B C E1 = A_ D1 E2 = A_ D2 where `A_` is the partially applied function `A`.
- tormeh 12y agoI understand currying and partial function application. That's not the problem. The problem is that function application whitespace demands an arbitrary application precedence and obscures function signature to the reader.
- tomp 12y agoah, that. Well, you get used to it. Also, it helps that application has the highest precedence, so it's quite easy to read expressions like `f x y + g z` (i.e. `(f x y) + (g z)`).
- michaelcampbell 12y ago> No, you're wrong. And you and he both gave evidence to the initial assertion that "it's confusing".
- gamegoblin 12y agoI'm not sure if "confusing" is fair -- just different than C-family languages. The rule is simply "The first expression is a function, all following expressions are arguments to that function" It's no different than "The first symbol is a function, all comma-separated, parentheses-bound expressions are arguments to that function" Both are pretty easy syntactic rules, I think.
- JoeAltmaier 12y agoIts arguably confusing, due to the lack of parentheses factoring a list of functions into one or more invocations. How is the nesting done here? Something more subtle. A lifetime of reading parenthesized functions is going to be confounded by changing the convention - which equals 'confusing'
- gamegoblin 12y agoI think you're probably overestimating the difference. Here is an algorithm for mechanically transforming a C function call to a Haskell function call: for all arguments in the function if the argument is not a symbol surround it with parentheses delete all commas delete the two initial parentheses And an algorithm for converting Haskell calls to C calls: put an open parenthesis between the first expression and second expression put a close parenthesis at the end of the expression put commas between all expressions between these two parentheses The fact that it's so easy to convert between them highlights to me that they are both pretty easy.
- gamegoblin 12y agoYou don't have to figure out which argument belongs to which function. The syntax is "The first expression is a function, all following expressions are arguments to that function". Fullstop. It would be unfair of me to say "C has confusing and ambiguous calling conventions, the compiler complains if I write A(B(C(D))) as A(B,C,D)" Because you would respond "Well of course, that's just the calling conventions of the language!" To which I say "Exactly"