|
|
Warp wrote:
> How does Haskell distinguish where a nested (possibly curried) function
> call ends, and the outer one continues? Assume that you would want to
> write (here in C++ style) something like:
>
> foo(a, bar(b, c), d, e)
>
> If you wrote that as a Haskell-style no-delimiters function call,
> I suppose it would look like:
>
> foo a bar b c d e
>
> Exactly how does Haskell decide how many parameters 'bar' takes there
> (and consequently how many of the rest of the parameters are for 'foo')?
You'd have to throw in some brackets to disambiguate.
If you change every "foo(x, y, z)" into "(foo x y z)", you'll get a
valid expression. In this case, we have
foo a (bar b c) d e
If you wrap the whole thing in brackets, then the following rule
applies: the first token after each "(" is the function being called;
everything else is arguments.
What may be a little confusing is that a function's arguments may be
functions themselves - even standard library functions. This is very
useful from a programming perspective (indeed, the whole paradigm is
based on it), but perhaps rather unhelpful for anybody trying to read
the thing.
Where this starts to go wrong is where you start using operators.
Obviously "2 + 7" means... well... two plus seven. It would be tedious
(though perhaps more consistent) to write this as "(+) 2 7".
To understand how to parse an expression involving operators, you must
know (or take a reasonable stab at) operator precidences. For arithmetic
operators, it's the usual stuff. Function application has a higher
precidence than anything else in the language - so "foo x + bar y"
parses as "(foo x) + (bar y)" and not "foo (x + bar) y".
And that leads us neatly on to...
> I can't even begin to imagine how you would write that using the
> "point syntax", seen in many examples posted by Andrew.
You can't. Because the nested expression isn't the final argument in the
argument list. (Haskell programmers are very fussy about what order to
put function arguments in for just this reason.)
> (Btw, I think this demonstrates one problem with Haskell. I'm an
> experienced programmer, and I do have a moderate understanding of the
> functional paradigm, and I have been seeing quite many example programs
> posted by Andrew during the last years. Yet I'm still completely unable
> to figure out or deduce how you could write that in Haskell. It must be
> simple, but I just don't know, even though I have seen many examples of
> small Haskell programs.
> There just is something about the Haskell paradigm and syntax that
> makes it confusing and hard to assimilate.)
The following are all equivilent:
function1 (function2 (function3 (function4 (function5 x))))
function1 $ function2 $ function3 $ function4 $ function5 $ x
function1 $ function2 $ function3 $ function4 $ function5 x
(function1 . function2 . function3 . function4 . function5) x
The last one creates a function by chaining several functions together,
and then passes x as the argument to that function. Normally you
wouldn't do that; you'd only use (.) if you wanted to pass a function as
an argument or something:
map (reverse . toUpper)
(Takes a list of strings, converts each string to upper case, and then
reverses it.)
Where this starts to get crazy is if you have functions that take more
than one argument. Because functions are curried, you may write
function2args x $ function4args a b c $ function1arg j
or something.
So, between recognising language keywords, bracketed expressions, ($)
and (.), and infix operators, I guess there *is* quite a bit to be
getting on with.
It's interesting to me that most people seem confused not by curried
functions or monads or high-order functions, but by the basics of
parsing Haskell's syntax. I guess I'm so used to it be now that I take
it for granted - but obviously, if you can't read the language syntax,
you don't stand much chance of getting very far. I'll go have a think
about that...
--
http://blog.orphi.me.uk/
http://www.zazzle.com/MathematicalOrchid*
Post a reply to this message
|
|