Function Precedence

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
36 messages Options
12
Reply | Threaded
Open this post in threaded view
|

Function Precedence

PR Stanley
Hi
If
f x = x
and
g y = y
then
f g x
returns an error because f takes only one argument. Why can't we have
function application implemented outwardly (inside-out). So
f g x would be applied with
gx first followed by its return value passed to f instead of putting
g x in brackets.

Cheers,
Paul

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

Janis Voigtlaender
PR Stanley wrote:
> Hi
> If
> f x = x
> and
> g y = y
> then
> f g x
> returns an error because f takes only one argument. Why can't we have
> function application implemented outwardly (inside-out).

Why should it be so?

> So
> f g x would be applied with
> gx first followed by its return value passed to f instead of putting g x
> in brackets.

You can get the same behavior with

  f . g $ x

if you mislike brackets.

--
Dr. Janis Voigtlaender
http://wwwtcs.inf.tu-dresden.de/~voigt/
mailto:[hidden email]
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

nornagon
In reply to this post by PR Stanley
On 01/04/2008, PR Stanley <[hidden email]> wrote:

> Hi
>  If
>  f x = x
>  and
>  g y = y
>  then
>  f g x
>  returns an error because f takes only one argument. Why can't we have
>  function application implemented outwardly (inside-out). So
>  f g x would be applied with
>  gx first followed by its return value passed to f instead of putting
>  g x in brackets.

Think about this:

map (+1) [1..10]

What should it do?

How about:

f 1 2 3

Should that be f (1 (2 3)), or ((f 1) 2) 3?

Jeremy
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

Jules Bean
In reply to this post by PR Stanley
PR Stanley wrote:
> Why can't we have
> function application implemented outwardly (inside-out).

No reason we can't.

We could.

We just don't.

People have spent some time thinking and experimenting and have decided
this way round is more convenient. It's certainly possible to disagree.

Jules
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

jerzy.karczmarczuk
In reply to this post by PR Stanley
Paul Stanley writes:

> Hi
> If
> f x = x
> and
> g y = y
> then
> f g x
> returns an error because f takes only one argument. Why can't we have
> function application implemented outwardly (inside-out)....
etc.

Paul,

There were already some answers, but it seems that people did not react to
the statement that f g x fails. It doesn't, in normal order everything
should go smoothly, f g 5 returns 5 = (f g) 5 = g 5, unless I am
terribly mistaken...
Where did you see an error?

Jerzy Karczmarczuk


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

Loup Vaillant
In reply to this post by Jules Bean
2008/4/1, Jules Bean <[hidden email]>:

> PR Stanley wrote:
>  > Why can't we have
>  > function application implemented outwardly (inside-out).
>
> No reason we can't.
>
>  We could.
>
>  We just don't.
>
>  People have spent some time thinking and experimenting and have decided
>  this way round is more convenient. It's certainly possible to disagree.

I bet this "time and thinking" involved currying. For instance, with:
f :: int -> int -> int
f a b = a + b + 3

Let's explore the two possibilities

(1) f 4 2 <=> (f 4) 2 -- don't need parentheses
(2) f 4 2 <=> f (4 2) -- do need parentheses: (f 4) 2

Curried functions are pervasive, so (1) just saves us more brakets
than (2) does.

> > f g x
> > returns an error because f takes only one argument.

Do not forget that *every* function take only one argument. The trick
is that the result may also be a function. Therefore,

f g 5 <=> id id 5 <=> (id id) 5 <=> id 5 <=> 5
indeed do run smoothly (just checked in the Ocaml toplevel, thanks to
Jerzy for pointing this out).

Loup
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

Hans Aberg
In reply to this post by PR Stanley
On 1 Apr 2008, at 12:40, PR Stanley wrote:
> Why can't we have function application implemented outwardly  
> (inside-out). So
> f g x would be applied with
> gx first followed by its return value passed to f instead of  
> putting g x in brackets.

It seems me it may come from an alteration of math conventions:  
Normally (x) = x, and function application is written as f(x), except  
for a few traditional names, like for example sin x. So if one  
reasons that f(x) can be simplified to f x, then f g x becomes short  
for f(g)(x) = (f(g))(x).

It is just a convention. In math, particularly in algebra, one  
sometimes writes "f of x" as x f or (x)f, so that one does not have  
to reverse the order for example in diagrams.

   Hans Aberg


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

PR Stanley
In reply to this post by nornagon

>Think about this:
>
>map (+1) [1..10]
>
>What should it do?
>         take (+1) and return a function which takes a list as its
> argument and finally return a list.


>How about:
>
>f 1 2 3
>
>Should that be f (1 (2 3)), or ((f 1) 2) 3?
         The latter, of course, but that's not really what I'm
driving at. I'm asking why we can't have a function treated
differently with regard to the precedence and associativity rules. f
1 2 is indeed ((f 1) 2). Why not f 1 g 2 == ((f 1) (g 2))?

Cheers, Paul

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

Chris Smith-39
PR Stanley wrote:
>>Should that be f (1 (2 3)), or ((f 1) 2) 3?
>          The latter, of course, but that's not really what I'm
> driving at. I'm asking why we can't have a function treated differently
> with regard to the precedence and associativity rules. f 1 2 is indeed
> ((f 1) 2). Why not f 1 g 2 == ((f 1) (g 2))?

Are you asking why one doesn't change the rules for all functions?  Or
are you asking why Haskell doesn't include a system of user-defined
precedence and associativity for function application so that one could
declare that g binds more tightly than f?  I see good reasons for both
questions, but I'm unsure which you mean.

In both cases, it comes down to consistency of the syntax rules.  In
order for (f 1 g 2) to parse as (f 1) (g 2), one would have to do
something surprising.  It's unclear what that is: perhaps treat literals
differently from variables?  Somehow determine a precedence level for
(f 1)?  Or maybe favor shorter argument lists for grouping function
application?

If you have a very clear kind of grouping that you think makes sense in
all cases, feel free to mention it.  It seems unlikely to me, but perhaps
everyone will agree, once they see it, that it is in fact better than the
current parsing rules.

--
Chris Smith

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re: Function Precedence

PR Stanley
Are you asking why one doesn't change the rules for all functions?  Or
are you asking why Haskell doesn't include a system of user-defined
precedence and associativity for function application so that one could
declare that g binds more tightly than f?  I see good reasons for both
questions, but I'm unsure which you mean.

In both cases, it comes down to consistency of the syntax rules.  In
order for (f 1 g 2) to parse as (f 1) (g 2), one would have to do
something surprising.  It's unclear what that is: perhaps treat literals
differently from variables?  Somehow determine a precedence level for
(f 1)?  Or maybe favor shorter argument lists for grouping function
application?

If you have a very clear kind of grouping that you think makes sense in
all cases, feel free to mention it.  It seems unlikely to me, but perhaps
everyone will agree, once they see it, that it is in fact better than the
current parsing rules.

Paul:
All you'd have to do is to give the inner most function the highest precdence
therefore
f g x == f (g x)
let f x = x^2
let g x = x`div`2
f g 4 == error while
f (g 4) == 4

I'm beginning to wonder if I fully understand the right associativity
rule for the -> operator.

Cheers, Paul

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Re: Function Precedence

Brandon S Allbery KF8NH

On Apr 1, 2008, at 17:07 , PR Stanley wrote:
> I'm beginning to wonder if I fully understand the right  
> associativity rule for the -> operator.

Read a parenthesized unit as an argument:

 > (a -> (b -> (c -> d)))         (((f 1) 2) 3)
 > (((a -> b) -> c) -> d)         (f (1 (2 3)))

--
brandon s. allbery [solaris,freebsd,perl,pugs,haskell] [hidden email]
system administrator [openafs,heimdal,too many hats] [hidden email]
electrical and computer engineering, carnegie mellon university    KF8NH


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

Chris Smith-39
In reply to this post by PR Stanley
PR Stanley wrote:
> All you'd have to do is to give the inner most function the highest
> precdence therefore
> f g x == f (g x)
> let f x = x^2
> let g x = x`div`2
> f g 4 == error while
> f (g 4) == 4

I'm afraid I still don't understand what you're proposing.  How can
f g x mean f (g x), and yet f g 4 is different from f (g 4)?

Maybe it'll help to point out that using functions as first-class
concepts -- including passing them around as data -- is fundamental to
functional programming languages.  In other words, anything in the world
could be a function, whether it's acting like a function right now or
not.  So distinguishing between (f g 4) and (f 1 2) is probably not
wise.  They either need to both parse like ((f g) 4), or they need to
both parse like (f (1 2)).  It has been the experience of the Haskell,
ML, and other related languages that left associativity for function
application works best.

> I'm beginning to wonder if I fully understand the right associativity
> rule for the -> operator.

It just means that if I have a string of things separated by ->, I can
put parentheses around all but the leftmost one, and it doesn't change
the meaning.

--
Chris Smith

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

Henning Thielemann
In reply to this post by Hans Aberg

On Tue, 1 Apr 2008, Hans Aberg wrote:

> On 1 Apr 2008, at 12:40, PR Stanley wrote:
> > Why can't we have function application implemented outwardly
> > (inside-out). So
> > f g x would be applied with
> > gx first followed by its return value passed to f instead of
> > putting g x in brackets.
>
> It seems me it may come from an alteration of math conventions:
> Normally (x) = x, and function application is written as f(x), except
> for a few traditional names, like for example sin x. So if one
> reasons that f(x) can be simplified to f x, then f g x becomes short
> for f(g)(x) = (f(g))(x).

In functional analysis you write e.g. D f(x) meaning (D f)(x) not D(f(x)),
so I wouldn't say there is any convention of precedence of function
application in mathematics. Even more, in functional analysis it is common
to omit the parentheses around operator arguments, and since there are a
lot of standard functions like 'sin', I wouldn't say that using argument
parentheses is more common than omitting them. (Btw. in good old ZX
Spectrum BASIC it was also allowed to omit argument parentheses.)
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

Hans Aberg

On 2 Apr 2008, at 11:22, Henning Thielemann wrote:

>> It seems me it may come from an alteration of math conventions:
>> Normally (x) = x, and function application is written as f(x), except
>> for a few traditional names, like for example sin x. So if one
>> reasons that f(x) can be simplified to f x, then f g x becomes short
>> for f(g)(x) = (f(g))(x).
>
> In functional analysis you write e.g. D f(x) meaning (D f)(x) not D
> (f(x)),
> so I wouldn't say there is any convention of precedence of function
> application in mathematics.

When I take a quick look into Hörmander's book on distributions, then  
he writes (D f)(phi), and not D f(phi). So there might be a  
difference between math that is drawn towards pure or applied math.

> Even more, in functional analysis it is common
> to omit the parentheses around operator arguments, and since there  
> are a
> lot of standard functions like 'sin', ...

I think that in RTL, one do that as well: x tau, instead of (x)tau.

> ...I wouldn't say that using argument
> parentheses is more common than omitting them.(Btw. in good old ZX
> Spectrum BASIC it was also allowed to omit argument parentheses.)

Math usage is probably in minority these days. As I noted, looking  
into books on axiomatic set theory, one construct tuplets it so that  
(x) = x. So it seems possible, although for function application f(z)  
seems the normal notation.

But one should also be able to write (f+g)(x). - This does not work  
in Haskell, because Num requires an instance of Eq and Show.

   Hans

_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

jerzy.karczmarczuk
Hans Aberg writes:

...
> But one should also be able to write (f+g)(x). - This does not work  in
> Haskell, because Num requires an instance of Eq and Show.

So, declare them, even if they are vacuous. I did it several times, I am
still alive, so no need to say "this does not work".

Jerzy Karczmarczuk


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

Hans Aberg
On 2 Apr 2008, at 13:51, [hidden email] wrote:
>> But one should also be able to write (f+g)(x). - This does not  
>> work  in Haskell, because Num requires an instance of Eq and Show.
>
> So, declare them, even if they are vacuous. I did it several times,  
> I am
> still alive, so no need to say "this does not work".

That is possible, of course - I did that, too. But it means that the  
syntax and semantics do not work together; an invitation to pitfalls.  
So this ought to be avoided, except if there are no other workarounds.

It would be better to write a new Prelude. :-)

   Hans


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

jerzy.karczmarczuk
Hans Aberg comments my remark to his observation:

>>> But one should also be able to write (f+g)(x). - This does not  work  in
>>> Haskell, because Num requires an instance of Eq and Show.
>>
>> So, declare them, even if they are vacuous. I did it several times,  I am
>> still alive, so no need to say "this does not work".
>
> That is possible, of course - I did that, too. But it means that the  
> syntax and semantics do not work together; an invitation to pitfalls.  So
> this ought to be avoided, except if there are no other workarounds.

I am more tolerant. The question - for me - is not an interplay between
syntax and semantics, syntax here is irrelevant, the fact that (+) is a
popular infix operator plays no role. The calamity comes from the fact that
it is not possible to write serious and "natural" instances of Eq and
Show for functions, and that for God knows which reasons, the Num instance
demands them ! This requirement is not rational, although intuitive. But
I violated it several times, when I needed arithmetic for lazy infinite
objects... So, I can't say that this should be avoided. I don't see
"obvious" pitfalls therein.

> It would be better to write a new Prelude. :-)

Oh, yes, our common dream...

Jerzy Karczmarczuk


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

Hans Aberg
On 2 Apr 2008, at 14:27, [hidden email] wrote:
>> That is possible, of course - I did that, too. But it means that  
>> the  syntax and semantics do not work together; an invitation to  
>> pitfalls.  So this ought to be avoided, except if there are no  
>> other workarounds.
>
> I am more tolerant.

The pragmatics is to decide whether to program Haskell, or making a  
new language. I am interested in the latter, but realistically nobody  
will singly be able prdocue the programingg capacity that the now  
mature Haskell has.

> The question - for me - is not an interplay between
> syntax and semantics, ...

That interplay, between notation and notions, is very important in  
math, as if the do not flow together, one will not be able to  
describe very complex logical structures.

> ...syntax here is irrelevant, the fact that (+) is a
> popular infix operator plays no role. The calamity comes from the  
> fact that
> it is not possible to write serious and "natural" instances of Eq and
> Show for functions, ...

A correct Eq would require a theorem prover. Show could be  
implemented by writing out the function closures, but I think the  
reason it is not there is that it would create overhead in compiled  
code.

> ...and that for God knows which reasons, the Num instance
> demands them ! This requirement is not rational, although intuitive.

Probably pragmatics. More general implementations were not considered  
at the time.

> But
> I violated it several times, when I needed arithmetic for lazy  
> infinite
> objects... So, I can't say that this should be avoided. I don't see
> "obvious" pitfalls therein.

The pitfall is when somebody which does not know the code well tries  
to use it. Define a library with
   false = True
   true = False
Perfectly logical, but it will be thwarted by peoples expectations.

>> It would be better to write a new Prelude. :-)
>
> Oh, yes, our common dream...

Such changes will require a new standard. Haskell seems rather fixed,  
so it will perhaps then happen in a new language. :-)

   Hans


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

Hans Aberg
In reply to this post by jerzy.karczmarczuk
On 2 Apr 2008, at 14:27, [hidden email] wrote:

>> It would be better to write a new Prelude. :-)
>
> Oh, yes, our common dream...

One may not need to write a wholly new Prelude, by something like:

module NewPrelude where

import Prelude hiding -- Num, (+).

class AdditiveSemiMonoid a where
   (+) :: a -> a -> a

...

class (Eq a, Show a, AdditiveSemiMonoid a) => Num a where
     (+)  :: a -> a -> a

-- Stuff of Prelude using Num.

Then import NewPrelude instead, and

instance AdditiveSemiMonoid (a -> b) where
   f + g = \x -> f(x) + g(x)

or something.

   Hans


_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
Reply | Threaded
Open this post in threaded view
|

Re: Function Precedence

Loup Vaillant
2008/4/2, Hans Aberg <[hidden email]>:

> On 2 Apr 2008, at 14:27, [hidden email]
> wrote:
>
> > > It would be better to write a new Prelude. :-)
> >
> > Oh, yes, our common dream...
>
>  One may not need to write a wholly new Prelude, by something like:
>
>  module NewPrelude where
>
>  import Prelude hiding -- Num, (+).
>
>  class AdditiveSemiMonoid a where
>   (+) :: a -> a -> a

Err, why *semi* monoid? Plain "monoid" would not be accurate?

<rant>
While we're at it, what about adding even more classes, like "group"
or "ring"? Algebra in a whole class hierachy. :-)
</rant>

Loup
_______________________________________________
Haskell-Cafe mailing list
[hidden email]
http://www.haskell.org/mailman/listinfo/haskell-cafe
12