

Second, a could_be(Type, Var) (analogy to must_be/2) that uses coroutining to allow the query to succeed at some point in the future: could_be(Type, X) :-įreeze_type(integer, X) :- freeze(X, integer(X)).įreeze_type(atom, X) :- freeze(X, atom(X)).įreeze_type(compound, X) :- freeze(X, compound(X)). Nonvar_has_type(compound, X) :- compound(X). Nonvar_has_type(integer, X) :- integer(X). This is a very naive attempt at implementing both your suggested solutions.įirst, has_type(Type, Var) that succeeds, or fails with an instantiation error: has_type(Type, X) :. If_(X = E, non_member(E, Es), unique(X, Es) ). The most efficient is probably the following which uses if_/3 of library(reif): unique(X, ) :. This uses non_member/2: unique(X, ) :-Īnd here is another way using tfilter/3: unique(X, Es) :. Also, your first rule needs to be reformulated. That conclusion is not true, consider to extend the list by X! You need some extra condition. In other words: Whenever I know that X is unique in Es, it will be also unique with any further element in Es. Provided X is a unique element of the list Es, then X is a unique element of the list. Reads declaratively, right-to-left (that :- is an ←) On the other hand, it gets quite frustrating receiving instantiation errors all the time instead of real answers. throw(error(domain_error(when_condition, Cond),_)) > ( Cond -> G_0 throw(error(instantiation_error,_)) )
Swi prolog tutorial examples iso#
Below is for any ISO conforming system: iwhen(Cond, G_0) :. ( var(Called) -> throw(error(instantiation_error,_)) true ).Ībove works for systems providing when/2.


This uses iwhen/2 which is similar to when/2 except that it does not delay: :- meta_predicate iwhen(+, 0). An immediate fix would be to guard your program against uses it is not designed for: unique(X, Xs) :. You have been using cut and an unsafe form of negation. They are monotonic, commutative and generally much easier to understand. The declarative solution to such problems are constraints, see for example dif/2. Such phenomena are common consequence of using meta-logical predicates. succeeds, but simply exchanging the order of goals does not yield the same result because ?- X = Y, addUnique(, 3), X = 0. Must_be/2 behaves monotonically, which is in general a nice property.Įxtending ony's comment: The problem is that (at least if the sample results above are correct) your predicate is no longer a true relation because goals are now not commutative: ?- X = 0, X = Y, addUnique(,3). Instead of integer/1, you should use must_be/2 from library(error) to obtain this sound behaviour: ?- must_be(integer, X).ĮRROR: Arguments are not sufficiently instantiated on the grounds that it does not have enough information to answer the question at this time. The "proper" (i.e., if you want nice monotonic predicates that make declarative sense) thing to do would be for integer/1 to raise an instantiation error on queries like ?- integer(X). But a more general goal, ?- integer(X)., fails!įor declarative debugging and automatically generated explanations, we expect that if a goal succeeds, every generalization of that goal must not fail. Take for example ?- integer(5)., which succeeds.

The fundamental problem of predicates like integer/1, atom/1 etc. % Have not assigned a value to this variable yet Integer(A), % <- THIS IS THE LINE IN QUESTION % Have already assigned a value to this variable % Base case: Assigned variables unique values Why is it bad practice to check if something is already defined to something else? Do you think it is bad practice? Are there other options that would be 'better practice'. I posted this solution to an question but ony left me a comment saying: Prolog Best Practice: checking if a variable is already bound.
