[mercury-users] higher order code

Fergus Henderson fjh at cs.mu.OZ.AU
Tue Oct 5 00:06:27 AEST 1999


On 04-Oct-1999, Michael Day <mikeday at corplink.com.au> wrote:
> 
> Is there a reason to use call(Predicate, Arg1, Arg2, ... ArgN) rather than
> Predicate(Arg1, Arg2, ... ArgN) directly?

No, not really.  `call/N' was there for Prolog compatibility.

> Is it possible to write predicates that take other predicates as
> arguments, with those predicates taking polymorphic arguments with
> typeclass constraints?

In general, no.  Higher-order predicate terms must be monomorphic.
That is, if you want to take the address of a polymorphic predicate
`foo' and pass it to a higher-order predicate `bar', then the choice
of which monomorphic instance of the polymorphic predicate `foo'
you will get must be made at the point where you take the address,
not at the point in `bar' where you actually call the predicate that
was passed.

> I've tried a few possibilities:
> 
> :- pred higher((pred(T) <= stringable(T))).
> 
> or
> 
> :- pred higher(pred(T)) <= stringable(T).
> 
> but I appear to be getting it wrong.

What you are looking for is higher-order polymorphism,
which Mercury currently does not support.
The syntax for it, if we were to support it, would almost certainly
look like this:

	:- pred higher(all [T] pred(T) <= stringable(T)).

Note that this differs from your attempts in the placement
of the quantifier.

The good news, however, is that there is a work-around:
you can use type classes.  Instead of

	:- pred foo(T) <= stringable(T).
	:- mode foo(in) is semidet.

	:- pred bar(all [T] pred(T) <= stringable(T)).
	:- mode bar(pred(in) is semidet) is semidet.
	bar(P) :- P(42), P("blah").

	:- pred baz is semidet.
	baz :- bar(foo).

it would look like this:

	:- pred foo(T) <= stringable(T).
	:- mode foo(in) is semidet.

	% This typeclass represents the type
	% `all [T] pred(T) <= stringable(T)'.
	:- typeclass stringable_pred(P) where [
		pred invoke(P, T) <= stringable(T),
		mode invoke(unused, in) is semidet
	].

	% Here instead of just calling `P' directly,
	% we call the `invoke' method.
	:- pred bar(P) <= stringable_pred(P).
	:- mode bar(in) is semidet.
	bar(P) :- invoke(P, 42), invoke(P, "blah").

	% Now we define a new type `foo_type' which represents
	% the predicate `foo' as a polymorphic higher-order term,
	% and declare an instance of the above typeclass
	% for this type.
	:- type foo_type ---> foo_type.
	:- instance stringable_pred(foo_type) where [
		pred(invoke/2) is invoke_foo
	].
	:- pred invoke_foo(foo_type, T) <= stringable(T).
	:- mode invoke_foo(unused, in) is semidet.
	invoke_foo(_, T) :- foo(T).

	% This is the same as above, except that we pass `foo_type'
	% instead of `foo'.
	% :- pred baz is semidet.
	baz :- bar(foo_type).

Cheers,
	Fergus.

-- 
Fergus Henderson <fjh at cs.mu.oz.au>  |  "I have always known that the pursuit
WWW: <http://www.cs.mu.oz.au/~fjh>  |  of excellence is a lethal habit"
PGP: finger fjh at 128.250.37.3        |     -- the last words of T. S. Garp.
--------------------------------------------------------------------------
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