	/* Higher-order and Meta-programming with apply and univ */
 
mode none.
closure none.

/*** This map function takes an arbitrary term and a function F that operates 
on constants, and returns a similar term with F applied to the constants ***/

map({X\_}, F) contains {map(X, F)}.
map([X|T], F) equals [map(X, F) | map(T,F)].
map(univ(C,L), F) equals univ(C,maplist(L,F)).	% other constructors
map(phi, F) equals phi.
map([], F)  equals [].
map(X, F) equals apply(F,X).			% constants

	maplist([],F)    equals [].
	maplist([H|T], F) equals [map(H,F) | maplist(T,F)]. 

/*** This is the plain old reduce function on lists ***/

reduce(F, [H])   equals H.
reduce(F, [H|T]) equals apply(F,H,reduce(F,T)).  

/******  Test Functions ****/

length([])    equals 0.
length([H|T]) equals 1 + length(T).

square(X) equals X*X.


/* Test Goals:

map([10,20,30],square).
map({10,20,{30}},square).
map([[10],20,[30,40]],square).
map([[1,2,3], [a,b,c,d,e], []],length).
map(foo(baz(10),baz(20)),square).

reduce(+, [1,2,3,4,5]).
*/
