Relay-Version: version B 2.10 5/3/83; site utzoo.UUCP
Path: utzoo!mnetor!uunet!seismo!vrdxhq!verdix!ogcvax!pase
From: pase@ogcvax.UUCP (Douglas M. Pase)
Newsgroups: comp.lang.misc
Subject: Re: H.O.Functions + Polymorphism
Message-ID: <1348@ogcvax.UUCP>
Date: Fri, 10-Jul-87 02:44:47 EDT
Article-I.D.: ogcvax.1348
Posted: Fri Jul 10 02:44:47 1987
Date-Received: Sun, 12-Jul-87 12:30:12 EDT
References: <1345@ogcvax.UUCP> 
Reply-To: pase@ogcvax.UUCP (Douglas M. Pase)
Distribution: world
Organization: Oregon Graduate Center, Beaverton, OR
Lines: 99

In the referenced article, pase@ogcvax.UUCP (Douglas M. Pase) wrote:
>
>...one is not able to directly bind arguments to a function and thereby
>create a new function:
>	let p1 = plus 1;
>This view of functions is thoroughly incompatible with that of any imperative
>language.

In article  jef@unisoft.UUCP (Jef Poskanzer) writes:
>
>int p1(x)
>int x;
>    {
>    return x + 1;
>    }

This misses the point completely.  Yes most people who claim to be even
remotely computer literate are able to write a function which has one
parameter and returns the sum of that parameter and one.  Suppose I wanted
you to write a function which accepted an arbitrary function (of one or more
parameters) and bind the number one as its first parameter.  This would be
considered a higher order function, because it is able to return a function
as its result.  In an SML-like language the function would be:

	let hof = \ f . f 1 ;

Many of you will recognize the '\' in the function as a 'lambda'.  The type
of 'hof' is

	hof : (int -> *a) -> *a

In other words, 'hof' is a function which accepts as its argument a function
which accepts an integer as *its* first argument and returns something of
unknown type.  'hof' then returns something of the same type as is returned
by its argument (it's obvious why).

Let's give a few examples to clarify just what this all means.  Suppose I
have the functions 's3' and 'm2' as follows:

	let s3 = \ x . \ y . \ z . x + y + z ;
	let m2 = \ x . \ y . x - y ;

's3' obviously sums three integers and 'm2' subtracts the second from the
first.  Their types are:

	s3 : int -> (int -> (int -> int))
	m2 : int -> (int -> int)

Now, I can use 'hof' to generate new functions as follows:

	let s2 = hof s3 ;	/* s2 : int -> (int -> int)	*/
	let m1 = hof m2 ;	/* m1 : int -> int		*/

's2' accepts two arguments, which it sums and adds '1'.  'm1' accepts one
argument which it subtracts from '1'.  The point of this discussion is not,
as it was previously misperceived, that I can create the functions 's2' and
'm1', but that I can create the function 'hof', from which I can create
*at runtime* the functions 's2' and 'm1'.  It is with the creation of 'hof'
that imperative languages have such difficulty.


>Or if you want to be polymorphic:
>
>#define p1(x) ((x) + 1)

This function, although it may be polymorphic in a limited sense, is certainly
not a higher order function.

I write:

>...lazy evaluation is not supportable in
>imperative languages as it is an 'evaluate on demand' strategy for function
>parameter evaluation.  All imperative languages evaluate the arguments to
>functions before the function is invoked.

Jef Poskanzer writes:

>Algol 60 had call-by-name over twenty years ago.  It wasn't useful then
>either.

Call-by-name has interesting semantics -- which are different from those
of lazy evaluation.  Lazy evaluation allows one to create and partially
evaluate infinite data structures.  An attempt to evaluate an infinite
data structure in an imperative language leads to an infinite loop.  Now
I must add that a programmer can be very clever and avoid the infinite loop,
but that is my point -- in an imperative language the programmer must write
clever programs.  A functional language which supports lazy evaluation will
allow the programmer to define the structure in a way that is more natural
to the problem, and leave the cleverness to the compiler.  That which would
be an infinite loop in an imperative language may have reasonable semantics
in such a functional language.

>The point about generic functions is valid, and many recent imperative
>languages support them.

I have seen some forms of ad-hoc polymorphism supported;  I have yet to see
the full capabilities of polymorphism become available.
--
Doug Pase   --   ...ucbvax!tektronix!ogcvax!pase  or  pase@Oregon-Grad.csnet