[mercury-users] unification problem
Fergus Henderson
fjh at cs.mu.OZ.AU
Fri Apr 30 11:51:44 AEST 2004
On 29-Apr-2004, Stefan Hinterstoisser <supersteveee at gmx.de> wrote:
> I have the following predicate:
>
> :- pred konto( string, string, string, string ).
> :- mode konto( in, in, out, out ) is nondet.
> :- mode konto( out, in, out, out ) is nondet.
> :- mode konto( in, out, out, out ) is nondet.
> :- mode konto( out, out, out, out ) is nondet.
> konto( "Vater", "Mutter", "true", "konto(Vater,Mutter);" ).
> konto( _, _, "false", "konto(false,false)" ).
>
> what I want is that this predicate (although definied as nondet) behaves
> like a predicate that always becomes true (and gave true and konto(Vater,
> Mutter) back if it matches Vater and Mutter and else false and
> konto(false,false) ).
The specification that you give has an infinite number of solutions
in the cases where either the first or second argument has mode "out".
> unfortunatly the wildcards dont fit because of missing
> groundness (because of the mode definition).
Yes. Mercury won't let you write a predicate with an infinite number
of solutions by just writing an underscore, since a predicate with
an infinite number of solutions is usually a bug.
> is there any way to get that
> demanded behavior I described before without changing the modes (and note:
> every mode type could also be used in the later program!)....
Yes. You could write the code so that it explicitly generates
an infinite number of solutions, like this:
konto( "Vater", "Mutter", "true", "konto(Vater,Mutter);" ).
konto( S1, S2, "false", "konto(false,false)" ) :-
not ( S1 = "Vater", S2 = "Mutter" ),
gen_string(S1),
gen_string(S2).
where gen_string is defined as
:- pred gen_string(string).
:- mode gen_string(in) is semidet. % really det, actually
:- mode gen_string(out) is nondet.
gen_string(S) :-
string.from_char_list(L, S),
gen_char_list(L).
:- pred gen_char_list(list(char)).
:- mode gen_char_list(in) is semidet. % really det, actually
:- mode gen_char_list(out) is nondet.
gen_char_list([]).
gen_char_list([C|Cs]) :- gen_char(C), gen_char_list(Cs).
:- pred gen_char(char).
:- mode gen_char(in) is semidet. % really det, actually
:- mode gen_char(out) is nondet.
gen_char(C) :-
char.to_int(C, I),
list.member(I, char.min_char_value `..` char.max_char_value),
However, any uses of gen_string in the (out) mode will lead to an infinite
number of solutions, which is probably not going to be helpful!
P.S.
For advanced students of Mercury, I should point out that it is possible
to use different clauses for different modes to implement this more
efficiently and with a more accurate determinism specification:
:- pred gen_string(string).
:- mode gen_string(in) is det.
:- mode gen_string(out) is nondet.
:- pragma promise_pure(gen_string/1).
gen_string(_::in).
gen_string(S::out) :-
string.from_char_list(L, S),
gen_char_list(L).
However, this technique should NOT be used unless the user is 100%
confident about the safety of the "promise_pure" annotation guaranteeing
that the different clauses have the same set of solutions, and it is
easy for novices to be wrong about that, so I do not recommend this
technique to novice users.
--
Fergus Henderson | "I have always known that the pursuit
| of excellence is a lethal habit"
WWW: <http://www.cs.mu.oz.au/~fjh> | -- 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