[mercury-users] Idea for a currying library

Richard A. O'Keefe ok at hermes.otago.ac.nz
Tue Jan 11 13:12:56 AEDT 2000


	On 07-Jan-2000, Ralph Becket <rbeck at microsoft.com> wrote:
	> Richard O'Keefe, I think, made the suggestion
	> that some extra syntax be introduced, e.g.
	> 
	> 	P = foo(X, #2, Y, #1)
	> 
	> would translate into
	> 
	> 	P = (func(A, B) = foo(X, B, Y, A))
	> 
	> or somesuch.

My memory is like a sieve with holes in it, but I'm pretty sure someone
else suggested that, and I attacked it.  I've had a strong dislike for
notations that require people to count, which is why I never really took
to Backus's FP, and why I'm sure I never suggested this, except perhaps as
a straw man.

	> If adding more syntax is undesirable/too much
	> trouble for now, it occurs to me that we could
	> get some way towards solving the problem with
	> a suitable library.  The idea would be to
	> provide currying functions for all the non-
	> standard argument permutations for all functions
	> up to a given arity, say 5.  This library would
	> look something like the following:

On the other hand, I've been using something very like this for years,
and could well have recommended *this* as a good enough notation.
Although I must say that I quickly abandoned it in Haskell and Clean;
"sections" are great for easy problems, but for hard ones, lambda-
notation is so much easier to get right.  I include a copy of my Prolog
module; the comment was revised for this mailing.

%   Module : callperm
%   Author : Richard A. O'Keefe
%   Updated: 2000.01
%   Defines: Permutative calls.

:- module(callperm, [
    %	call/1,

	call_1/2,

	call_1_2/3,
	call_2_1/3,

	call_1_2_3/4,
	call_1_3_2/4,
	call_2_1_3/4,
	call_2_3_1/4,
	call_3_1_2/4,
	call_3_2_1/4,

	call_1_2_3_4/5,
	call_1_3_2_4/5,
	call_2_1_3_4/5,
	call_2_3_1_4/5,
	call_3_1_2_4/5,
	call_3_2_1_4/5,
	call_1_2_4_3/5,
	call_1_3_4_2/5,
	call_2_1_4_3/5,
	call_2_3_4_1/5,
	call_3_1_4_2/5,
	call_3_2_4_1/5,
	call_1_4_2_3/5,
	call_1_4_3_2/5,
	call_2_4_1_3/5,
	call_2_4_3_1/5,
	call_3_4_1_2/5,
	call_3_4_2_1/5,
	call_4_1_2_3/5,
	call_4_1_3_2/5,
	call_4_2_1_3/5,
	call_4_2_3_1/5,
	call_4_3_1_2/5,
	call_4_3_2_1/5
   ]).
:- use_module(library(call), [
	call/2,
	call/3,
	call/4,
	call/5
   ]).
:- meta_predicate
    %   call(0),
	call_1(1, ?),
	call_1_2(2, ?, ?),
	call_2_1(2, ?, ?),

	call_1_2_3(3, ?, ?, ?),
	call_1_3_2(3, ?, ?, ?),
	call_2_1_3(3, ?, ?, ?),
	call_2_3_1(3, ?, ?, ?),
	call_3_1_2(3, ?, ?, ?),
	call_3_2_1(3, ?, ?, ?),

	call_1_2_3_4(4, ?, ?, ?, ?),
	call_1_3_2_4(4, ?, ?, ?, ?),
	call_2_1_3_4(4, ?, ?, ?, ?),
	call_2_3_1_4(4, ?, ?, ?, ?),
	call_3_1_2_4(4, ?, ?, ?, ?),
	call_3_2_1_4(4, ?, ?, ?, ?),
	call_1_2_4_3(4, ?, ?, ?, ?),
	call_1_3_4_2(4, ?, ?, ?, ?),
	call_2_1_4_3(4, ?, ?, ?, ?),
	call_2_3_4_1(4, ?, ?, ?, ?),
	call_3_1_4_2(4, ?, ?, ?, ?),
	call_3_2_4_1(4, ?, ?, ?, ?),
	call_1_4_2_3(4, ?, ?, ?, ?),
	call_1_4_3_2(4, ?, ?, ?, ?),
	call_2_4_1_3(4, ?, ?, ?, ?),
	call_2_4_3_1(4, ?, ?, ?, ?),
	call_3_4_1_2(4, ?, ?, ?, ?),
	call_3_4_2_1(4, ?, ?, ?, ?),
	call_4_1_2_3(4, ?, ?, ?, ?),
	call_4_1_3_2(4, ?, ?, ?, ?),
	call_4_2_1_3(4, ?, ?, ?, ?),
	call_4_2_3_1(4, ?, ?, ?, ?),
	call_4_3_1_2(4, ?, ?, ?, ?),
	call_4_3_2_1(4, ?, ?, ?, ?).


/*  The basic idea of these predicates is that

	call_<pi[1]>..._<pi[n]>(p(X1,...,Xm), Y1,...,Yn) :-
	    p(X1, ..., Xm, Y<pi[1]>, ..., Y<pi[n]>).

    where pi[] is a permutation of 1..n.

    Oddly enough, they are not meant to be called directly.  If you can
    write call_2_1_3(P, Y, X, Z) directly, then you could have written
    call(P, X, Y, Z) directly, and more clearly.  The idea is that you
    can use these things to build closures that can be passed around and
    called using the call/N family, and decide the argument order at the
    point where the closure is MADE (not called).  To take a specific
    example, if you want to check whether all the elements of a list are
    strictly positive, the obvious thing is to write

	maplist(>(0), Numbers)

    It may be obvious, but it's wrong.  You have to write <(0) instead,
    which is counter-intuitive, and the converse relation isn't always
    available.  What you can do with the aid of this module is write

	maplist(call_2_1(>,0), Numbers).

    Let's see how that works.  Let's say the first element of the list
    is 137.  Then maplist/2 will do

	call(call_2_1(>,0), 137)
    :-  call_2_1(>, 0, 137)
    :-  call(>, 137, 0)
    :-  137 > 0

    which is what we want.

    There are two reasons why this set of permutative calls stops at 4
    additional arguments.  The first is that we'd need 120 predicates to
    handle 5 arguments.  The second is that even with 4 arguments I have
    to stop and draw a diagram to make sure I'm using these things
    correctly; the notation (like all notations that require people to
    count) simply doesn't scale well.
*/

/*
call(G) :- call(G).
*/

call_1(G, Y1) :- call(G, Y1).

call_1_2(G, Y1, Y2) :- call(G, Y1, Y2).
call_2_1(G, Y1, Y2) :- call(G, Y2, Y1).

call_1_2_3(G, Y1, Y2, Y3) :- call(G, Y1, Y2, Y3).
call_1_3_2(G, Y1, Y2, Y3) :- call(G, Y1, Y3, Y2).
call_2_1_3(G, Y1, Y2, Y3) :- call(G, Y2, Y1, Y3).
call_2_3_1(G, Y1, Y2, Y3) :- call(G, Y2, Y3, Y1).
call_3_1_2(G, Y1, Y2, Y3) :- call(G, Y3, Y1, Y2).
call_3_2_1(G, Y1, Y2, Y3) :- call(G, Y3, Y2, Y1).

call_1_2_3_4(G, Y1, Y2, Y3, Y4) :- call(G, Y1, Y2, Y3, Y4).
call_1_3_2_4(G, Y1, Y2, Y3, Y4) :- call(G, Y1, Y3, Y2, Y4).
call_2_1_3_4(G, Y1, Y2, Y3, Y4) :- call(G, Y2, Y1, Y3, Y4).
call_2_3_1_4(G, Y1, Y2, Y3, Y4) :- call(G, Y2, Y3, Y1, Y4).
call_3_1_2_4(G, Y1, Y2, Y3, Y4) :- call(G, Y3, Y1, Y2, Y4).
call_3_2_1_4(G, Y1, Y2, Y3, Y4) :- call(G, Y3, Y2, Y1, Y4).

call_1_2_4_3(G, Y1, Y2, Y3, Y4) :- call(G, Y1, Y2, Y4, Y3).
call_1_3_4_2(G, Y1, Y2, Y3, Y4) :- call(G, Y1, Y3, Y4, Y2).
call_2_1_4_3(G, Y1, Y2, Y3, Y4) :- call(G, Y2, Y1, Y4, Y3).
call_2_3_4_1(G, Y1, Y2, Y3, Y4) :- call(G, Y2, Y3, Y4, Y1).
call_3_1_4_2(G, Y1, Y2, Y3, Y4) :- call(G, Y3, Y1, Y4, Y2).
call_3_2_4_1(G, Y1, Y2, Y3, Y4) :- call(G, Y3, Y2, Y4, Y1).

call_1_4_2_3(G, Y1, Y2, Y3, Y4) :- call(G, Y1, Y4, Y2, Y3).
call_1_4_3_2(G, Y1, Y2, Y3, Y4) :- call(G, Y1, Y4, Y3, Y2).
call_2_4_1_3(G, Y1, Y2, Y3, Y4) :- call(G, Y2, Y4, Y1, Y3).
call_2_4_3_1(G, Y1, Y2, Y3, Y4) :- call(G, Y2, Y4, Y3, Y1).
call_3_4_1_2(G, Y1, Y2, Y3, Y4) :- call(G, Y3, Y4, Y1, Y2).
call_3_4_2_1(G, Y1, Y2, Y3, Y4) :- call(G, Y3, Y4, Y2, Y1).

call_4_1_2_3(G, Y1, Y2, Y3, Y4) :- call(G, Y4, Y1, Y2, Y3).
call_4_1_3_2(G, Y1, Y2, Y3, Y4) :- call(G, Y4, Y1, Y3, Y2).
call_4_2_1_3(G, Y1, Y2, Y3, Y4) :- call(G, Y4, Y2, Y1, Y3).
call_4_2_3_1(G, Y1, Y2, Y3, Y4) :- call(G, Y4, Y2, Y3, Y1).
call_4_3_1_2(G, Y1, Y2, Y3, Y4) :- call(G, Y4, Y3, Y1, Y2).
call_4_3_2_1(G, Y1, Y2, Y3, Y4) :- call(G, Y4, Y3, Y2, Y1).

end_of_file.
--------------------------------------------------------------------------
mercury-users mailing list
post:  mercury-users at cs.mu.oz.au
administrative address: owner-mercury-users at cs.mu.oz.au
unsubscribe: Address: mercury-users-request at cs.mu.oz.au Message: unsubscribe
subscribe:   Address: mercury-users-request at cs.mu.oz.au Message: subscribe
--------------------------------------------------------------------------



More information about the users mailing list