As we've seen, Hope functions possess `full rights' and can be passed as actual parameters like any data object. It'll be no surprise to learn that we can return a function as the result of another function. The result can be a named function or an anonymous function defined by a lambda-expression. Here's a simple example:
dec makestep : num -> ( num -> num ) ;
--- makestep ( i ) <= lambda ( x ) => i + x ;
makestep ( 3 ) ;
lambda ( x ) => 3 + x : num -> num
As we can see from trying makestep, its result is an anonymous function
that adds a fixed quantity to its single argument. The size of the increment
was specified as an actual parameter to makestep when the new function was
created, and has become `bound in' to its definition. If we try the new
function, we'll see that it really does add 3 to its actual parameter:
makestep ( 3 ) ( 10 ) ;
13 : num
There are two applications here. First we apply makestep to 3, then the
resulting anonymous function is applied to 10. Finally, here's a function
that has functions as both actual parameter and result:
dec twice : ( alpha -> alpha ) -> ( alpha -> alpha ) ;
--- twice ( f ) <= lambda ( x ) => f ( f ( x ) ) ;
twice defines a new function that has a single argument and some other
function f bound into its definition. The new function has the same type
as f. We can see its effect using a simple function like square:
twice ( square ) ;
lambda ( x ) => square( square ( x ) ) : num -> num
twice ( square ) ( 3 ) ;
81 : num
The new function applies the bound-in function to its argument twice. We can
even bind in twice itself, generating a new function that behaves like
twice except that the function eventually bound in will be applied four
times:
twice ( twice ) ;
lambda ( x ) => twice ( twice ( x ) ) :
( alpha -> alpha ) -> ( alpha -> alpha )
twice ( twice ) ( square ) ( 3 ) ;
43046721 : num