Result of over-applied function

14 views
Skip to first unread message

DAY

unread,
Jun 13, 2012, 2:12:56 AM6/13/12
to pure...@googlegroups.com
Hi,


I notice that in Pure, a function of fixed arity can be over-applied, for example:

> max 1 2 3
2 3

Is this controversial behavior a feature?  If it is, what is the motivation?  Thanks.

John Cowan

unread,
Jun 13, 2012, 3:27:00 AM6/13/12
to pure...@googlegroups.com
DAY scripsit:
All Pure functions are of fixed arity, to begin with: max has arity 2.
So since max 1 2 3 is synonymous with (max 1 2) 3, inside-to-outside
rewriting produces 2 3, the application of 2 to 3. Since it is not
possible to define rewrite rules whose head is a non-symbol[*], 2 3 is
necessarily in normal form.

[*] Not true in Pure's predecessor Q, where you could actually write
"2 3 = 6". The Q engine knows nothing of functions: application just
causes a rule to be searched for. Pure aggregates rules with a common
head into functions which are then fed to LLVM.

--
Do what you will, John Cowan
this Life's a Fiction co...@ccil.org
And is made up of http://www.ccil.org/~cowan
Contradiction. --William Blake

Yi Dai

unread,
Jun 13, 2012, 3:36:02 AM6/13/12
to pure...@googlegroups.com
On Wed, Jun 13, 2012 at 9:27 AM, John Cowan <co...@mercury.ccil.org> wrote:
DAY scripsit:

> I notice that in Pure, a function of fixed arity can be over-applied, for
> example:
>
> > max 1 2 3
> 2 3
>
> Is this controversial behavior a feature?  If it is, what is the
> motivation?  Thanks.

All Pure functions are of fixed arity, to begin with:  max has arity 2.
So since max 1 2 3 is synonymous with (max 1 2) 3, inside-to-outside
rewriting produces 2 3, the application of 2 to 3.

Applying 2 to 3 seems so weird and it is even so when such an over-application is used, for example,

> max 1 2 3 + 4
2 3 + 4

Even in a dynamically-typed setting, one would expect a dynamic error.  
 
Since it is not possible to define rewrite rules whose head is a non-symbol[*], 2 3 is
necessarily in normal form.

According to your answer, it seems this strange behavior is a consequence of Pure's TRS base.  But is it a feature or misfeature.  If it is the former, any scenario for its use?

 

[*] Not true in Pure's predecessor Q, where you could actually write
"2 3 = 6".  The Q engine knows nothing of functions: application just
causes a rule to be searched for.  Pure aggregates rules with a common
head into functions which are then fed to LLVM.

--
Do what you will,                       John Cowan
  this Life's a Fiction                co...@ccil.org
And is made up of                       http://www.ccil.org/~cowan
  Contradiction.  --William Blake

--
You received this message because you are subscribed to the Google Groups "pure-lang" group.
To post to this group, send email to pure...@googlegroups.com.
To unsubscribe from this group, send email to pure-lang+...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/pure-lang?hl=en.


Albert Graef

unread,
Jun 13, 2012, 12:17:19 PM6/13/12
to pure...@googlegroups.com
On 06/13/2012 09:36 AM, Yi Dai wrote:
> Applying 2 to 3 seems so weird and it is even so when such an
> over-application is used, for example,
>
>> max 1 2 3 + 4
> 2 3 + 4
>
> Even in a dynamically-typed setting, one would expect a dynamic error.

That doesn't happen in Pure because of the term rewriting semantics. You
won't usually get an exception in Pure because that interferes with
symbolic evaluation of expressions. E.g., the following computation is
perfectly legal in Pure, with f, g, x, y, z and t being free (undefined)
symbols:

> (f x . g y) z t;
f x (g y z) t

If you're too lazy to invent variable names, you might as well write:

> (1 2 . 3 4) 5 6;
1 2 (3 4 5) 6

That kind of stuff would be precluded in a language which forbids
anything but a closure in the head position of a function application.
Actually that's the case in virtually every other FPL (except maybe
computer algebra systems), but I think of this as a very important
feature of Pure.

Also note that in Pure "constructor terms" are just applications of a
free symbol to some arguments, such as [1] === 1:[] === (:) 1 []. So
there's no distinction between "normal" function applications and
constructor terms like in Haskell et al. I consider this design
minimalistic and elegant.

> According to your answer, it seems this strange behavior is a
> consequence of Pure's TRS base. But is it a feature or misfeature. If
> it is the former, any scenario for its use?

As pointed out above, Pure allows any free symbol in the head position
of a function application, so it would be a rather arbitrary restriction
to forbid a number (or anything else which is not a symbol or an
application) there.

It's true that from the practical POV a normal form like 2 3 isn't
usually of much use since, as John pointed out, you can't have a rule
that defines a "headless" application of the form x::int y::int right
now. But you might still use them as constructor terms, so you could
define something like:

> foo (x@_ y) = x*y;
> foo (2 3);
6

Whether that's actually useful in some cases is left to your
imagination. But at least it's possible. Pure is much more permissive
than languages with the H/M safety net, so it doesn't put many
restrictions on the forms of terms.

In this context I just can't help taking the opportunity to link to this
again: http://www.lisperati.com/landoflisp/panel01.html. Enjoy. :)

Albert

--
Dr. Albert Gr"af
Dept. of Music-Informatics, University of Mainz, Germany
Email: Dr.G...@t-online.de, a...@muwiinfa.geschichte.uni-mainz.de
WWW: http://www.musikinformatik.uni-mainz.de/ag

Dubiousjim

unread,
Jun 13, 2012, 1:16:06 PM6/13/12
to pure...@googlegroups.com
On Wed, Jun 13, 2012 at 06:17:19PM +0200, Albert Graef wrote:

> As pointed out above, Pure allows any free symbol in the head position
> of a function application, so it would be a rather arbitrary restriction
> to forbid a number (or anything else which is not a symbol or an
> application) there.
>
> It's true that from the practical POV a normal form like 2 3 isn't
> usually of much use since, as John pointed out, you can't have a rule
> that defines a "headless" application of the form x::int y::int right
> now. But you might still use them as constructor terms, so you could
> define something like:
>
> > foo (x@_ y) = x*y;
> > foo (2 3);
> 6
>
> Whether that's actually useful in some cases is left to your
> imagination. But at least it's possible. Pure is much more permissive
> than languages with the H/M safety net, so it doesn't put many
> restrictions on the forms of terms.

When I was earlier reviewing different patterns for returning multiple values
from a function, I also considered (but didn't mention) this
possibility. Since I knew that one of the values I was returning was an
int, I could just shuffle it into head position and do:

foo _ = intval b c;
bar x = case foo x of
1 b c = blah;
0 b c = [b,c];
end;

and so on. It'd probably perform even better than what I ended up using:

foo _ = triple intval b c;
bar x = case foo x of
triple 1 b c = blah;
triple 0 b c = [b,c];
end;

or '(intval, b, c), or anything else of that sort.

But I couldn't bring myself to do it. It felt like I'd just be asking
for trouble down the road. At a minimum, you wouldn't want anyone to
emulate this pattern blindly.

--
Dubiousjim
dubio...@gmail.com

Yi Dai

unread,
Jun 14, 2012, 1:47:42 PM6/14/12
to pure...@googlegroups.com
Thanks for the detailed explanation, Albert.
 

> According to your answer, it seems this strange behavior is a
> consequence of Pure's TRS base.  But is it a feature or misfeature.  If
> it is the former, any scenario for its use?

As pointed out above, Pure allows any free symbol in the head position
of a function application, so it would be a rather arbitrary restriction
to forbid a number (or anything else which is not a symbol or an
application) there.

It's true that from the practical POV a normal form like 2 3 isn't
usually of much use since, as John pointed out, you can't have a rule
that defines a "headless" application of the form x::int y::int right
now. But you might still use them as constructor terms, so you could
define something like:

 > foo (x@_ y) = x*y;
 > foo (2 3);
 6

Whether that's actually useful in some cases is left to your
imagination. But at least it's possible. Pure is much more permissive
than languages with the H/M safety net, so it doesn't put many
restrictions on the forms of terms.

In this context I just can't help taking the opportunity to link to this
again: http://www.lisperati.com/landoflisp/panel01.html. Enjoy. :)

I saw the comics long time ago. Although I do use Haskell, it does not mean I am in that camp. Generally, I many Pure's design interesting and like to see the motivation behind it.
 

Albert

--
Dr. Albert Gr"af
Dept. of Music-Informatics, University of Mainz, Germany
Email:  Dr.G...@t-online.de, a...@muwiinfa.geschichte.uni-mainz.de
WWW:    http://www.musikinformatik.uni-mainz.de/ag

Albert Graef

unread,
Jun 14, 2012, 11:40:48 PM6/14/12
to pure...@googlegroups.com
On 06/14/2012 07:47 PM, Yi Dai wrote:
> I saw the comics long time ago. Although I do use Haskell, it does not
> mean I am in that camp. Generally, I many Pure's design interesting and
> like to see the motivation behind it.

Haskell is a cool language, I like it very much. Its safety comes at a
price, though, that's all I wanted to say. :)
Reply all
Reply to author
Forward
0 new messages