[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