[m-users.] A predicate taking a lists of predicates as input?
Zoltan Somogyi
zoltan.somogyi at runbox.com
Fri Sep 26 15:28:39 AEST 2025
On Wed, 24 Sep 2025 17:35:50 +0200, Anders Lundstedt <mercury-users at anderslundstedt.se> wrote:
> Sorry, tried to simplify too much. Here is a correct example:
>
> :- pred r_a(list(char)::in, list(char)::out) is semidet.
> :- pred r_b(list(char)::in, list(char)::out) is semidet.
> r_a --> ['a'].
> r_b --> ['b'].
> % gives compilation error, but not if the both the determinism of ? and of
> % this predicate is changed to semidet, in which case we get warnings about
> % too loose determinism for ?
> :- pred test_1(list(char)::in, list(char)::out) is det.
> test_1 --> ?([r_a, ?([r_b])]).
The issue here is that your ? predicate (which I will call "optional") is det,
but seems to take a list of semidet predicates (closures), which causes
a determinism mismatch if you want to include a closure of optional
itself in one of those lists.
The simple solution here is to put a wrapper around this closure to do
what is effectively a determinism cast. This can be done using code
like this:
:- pred optional_semidet(...) is semidet.
optional_semidet(In, Out) :-
( if semidet_succeed then
optional(In, Out)
else
fail
).
Operationally, this does exactly the same as optional(In, Out), but
the compiler handles it as a semidet predicate that just happens
to always succeed.
Then, whenever you want to put a closure of optional in a position
where you need a det predicate, you pass a closure of optional_semidet
instead.
I would also point you to the link named "The XY problem" on the
https://mercurylang.org/contact.html page. It seems applicable
in this instance.
Zoltan.
More information about the users
mailing list