[m-dev.] Automatic generation of map, foldr, foldl

Peter Schachte pets at cs.mu.OZ.AU
Mon Sep 21 15:59:17 AEST 1998


On Mon, Sep 21, 1998 at 02:25:28PM +1000, Fergus Henderson wrote:
> On 09-Sep-1998, Peter Schachte <pets at cs.mu.OZ.AU> wrote:
> > One thought, though.  One way of abstracting part of what all of these
> > predicates do is with the concept of an "iterator" (I know, I know,
> > this word brings to mind horrible images of C++, but it's a pretty
> > good description).  I guess it's best to think of iterator as a family
> > of type classes iterator_n(T,CT,IT) where T is a type (or a tuple of
> > types somehow?), CT is a collection of T, and IT is an iterator for
> > that collection.  Instances of iterator1 provide these predicates and
> > functions:
> > 
> > 	:- func iterator(CT::in) = IT::out is det.
> > 	:- pred next(IT::in, IT::out, T::out) is semidet.
> ...
> > Anyway, given just this, you can write a lot of the sorts of
> > higher-order predicates you're talking about generating once, and put
> > them in the library.  Eg, member is
> > 
> > 	:- pred member(T::out, CT::in) is nondet <= iterator1(T,CT,IT).
> 
> That won't work; you're not allowed to put constraints on type
> variables such as `IT' which don't occur in the predicate's
> arguments.

Yup, I pushed it too far; I forgot to reply to my own message to
correct this.  Instead of what I was suggesting earlier, I now suggest
a family of typeclasses iterator_n(T1,... Tn, IT) indicating that IT
is an iterator of types T1 to Tn.  This promises only the operations

	:- pred next(IT::in, IT::out, T1::out, ... Tn::out) is semidet.
	:- pred finished(IT::in) is semidet.

Then a generalized member/2 could be defined as

	:- predicate member(T, IT) <= iterator(IT, T).

	member(E, It) :-
		next(It, It1, E1),
		(   E1 = E
		;   member(E, It1)
		).

and called as

	member(E, iterator(L))

where

	:- func iterator(list(T)) = list(T)
	iterator(L) = L.

	:- instance iterator1(list(T), T).
	next([H|T], T, H).
	finished([]).

and

	:- type int_range ---> int - int.

	:- instance iterator1(int_range, int).
	next(Low-High, Low, Low+1..High) :- Low =< High.
	finished(Low-High) :- High = Low-1.

and

	:- type tree(T) ---> leaf ; tree(tree(T), T, tree(T)).
	:- type tree_inorder(T) --->
		(   empty 
		;    down(tree(T), tree_inorder(T))
		;    up(tree(T), tree_inorder(T))
		).

	:- func inorder(tree(T)) = tree_inorder(T)
	inorder(T) = down(T, empty).

	:- instance iterator1(tree_inorder(T), T).
	next(down(leaf, Stack0), E, Stack) :-
		next(Stack0, E, Stack).
	next(down(tree(L,E,R), Stack0), E1, Stack) :-
		next(down(L, up(tree(L,E,R), Stack0)), E1, Stack).
	next(up(tree(_,E,R), Stack), E, down(R, Stack)).
	finished(empty).


and map/3 could be defined as:

	:- pred map(pred(T1,T2), IT) <= iterator2(IT, T1, T2).

	map(P, It) :-
		(   next(It, It1, X1, X2) ->
			P(X1, X2),
			map(P, It1)
		;   finished(It)
		).

and invoked as

	map(pred(X,X+1), iterator(List,Successors))

(assuming pred(X,X+1) is the right syntax), where

	:- func iterator(list(T1), list(T2)) = pair(list(T1), list(T2)).
	iterator(L1, L2) = L1-L2

	:- instance iterator2(pair(list(T1), list(T2)), T1, T2).
	next([H1|T1]-[H2|T2], T1-T2, H1, H2).
	finished([]-[]).

I wonder if deforestation is smart enough to remove the unnecessary
construction of iterator data structures?

The interesting bit comes in when you make an iterator that is a pair
of other iterators, so both length and iota (a la apl) can be defined
as a simple operation over a pair of a list and integer range
iterator.  You need the concept of accumulators to handle folding, but
they can be defined, too.  Also, a nicer syntax, perhaps some sort of
`forall' syntax, would make this a lot more pleasant.

I'll leave the discussion of these points to another message.


-- 
Peter Schachte                | The question of whether a computer can think
mailto:pets at cs.mu.OZ.AU       | is no more interesting than the question of
http://www.cs.mu.oz.au/~pets/ | whether a submarine can swim.
PGP: finger pets at 128.250.37.3 |     -- E. W. Dijkstra 



More information about the developers mailing list