[m-dev.] Re: Visual vs total arity clash example [fwd]

Ralph Becket rbeck at microsoft.com
Sat Jan 29 02:29:31 AEDT 2000


> Hmm, let's see what foldl2 looks like with vars and call-site 
> annotation in Ralph's New Syntax:
> 
> :- pred foldl2(pred(T) + var(x, y), list(T)) + var(x, y).
> 
> foldl2(P, Xs) + var(x, y) -->>
> 	(
> 		Xs = []
> 	;
> 		Xs = [H | T],
> 		P(H) + var(x, y),
> 		fold2(P, T) + var(x, y)
> 	).

Thinking more about this, I think we might be able to do away
with the `htype' etc. declarations.  Consider:

:- pred foldl2(pred(T) + var(x, y), list(T)) + var(x, y).
:- mode foldl2(pred(in) + var((in,out),(in,out)) is det, in) +
	var((in,out),(in,out)) is det.

would have the obvious expansion:

:- pred foldl2(pred(T, TX, TX, TY, TY), list(T), TX, TX, TY, TY).
:- mode foldl2(pred(in, in, out, in, out) is det,
	in, out, in, out)	is det.

although some sort of abbreviation for var((in,out), ...) might
be nicer.

Actually, we should constrain the types of some var args and
not name higher-order var args

:- pred(foldl2(pred(T) + var(TX, TY), list(T)) + var(x:TX, y:TY).

since, as we're annotating EDCG call sites, we don't need to
specify names for higher order var args.

The code transformation is relatively straight-forward too:

foldl2(P, Xs, X0, X, Y0, Y) :-
	(
		Xs = [], X = X0, Y = Y0
	;
		Xs = [H | T],
		P(H, X0, X1, Y0, Y1),
		foldl2(P, T, X1, X, Y1, Y)
	).
		
we get higher-order expansion for nothing.

The question is whether or not to go for explicit annotation.
I argue that explicit annotation has the following pros:
1. the transformation is easy;
2. it is clear what is being being changed imperatively at
each EDCG call site;
3. we no longer need to name state threads globally (or at
least at the module level);
4. there is no problem integrating this stuff with non-EDCG
code;
5. higher order code is handled naturally.

The cons are:
1. one has to type a *little* more at each EDCG call site;
2. er, that's it.

If we look at the code for foldl2 under the current EDCG
recommendation, we see something like

:- pred foldl2(pred(T) + hidden(changes(x), changes(y)), list(T)) +
	hidden(changes(x), changes(y)).

foldl2(P, Xs) -->>
	(
		Xs = []
	;
		Xs = [H | T],
		P(H),
		foldl2(P, T)
	).

which looks far more like it's checking P against each member of Xs
rather than doing any processing of hidden args.  Compare the above
with

:- pred forall(pred(T), list(T)).

forall(P, Xs) :-
	(
		Xs = []
	;
		Xs = [H | T],
		P(H),
		forall(P, T)
	).

Lo, the only way to work out that something different is going on in
the foldl2 example is to spot the `-->>' and look at the pred
declaration.  Any code that also calls other (non-higher order) preds
will require the programmer to go look at the pred declarations for
those, too, in order to be sure he understands what is going on.

Sorry to keep harping on, but I feel quite strongly about this
point!

Ralph
--------------------------------------------------------------------------
mercury-developers mailing list
Post messages to:       mercury-developers at cs.mu.oz.au
Administrative Queries: owner-mercury-developers at cs.mu.oz.au
Subscriptions:          mercury-developers-request at cs.mu.oz.au
--------------------------------------------------------------------------



More information about the developers mailing list