Predicates that are implemented in terms of impure or semipure predicates are assumed to have the least of the purity of the goals in their body. The declared purity of a predicate must not be more pure than the inferred purity; if it is, the compiler must generate an error. If the declared purity is less pure than the inferred purity, the compiler should issue a warning (this is similar to the above case for goals). Because the inferred purity of the predicate is calculated from the declared purity of the calls it executes, the lowest purity bound is propagated up from callee to caller through the program.
In some cases the impurity of a predicate’s body is an implementation detail which should not be exposed to callers. These predicates are pure or semipure even though they call impure or semipure predicates. The only way for the programmer to stop the propagation of impurity is to explicitly promise that the predicate or function is pure or semipure.
Of course, the Mercury compiler cannot verify that the predicate’s purity matches the promise, so it is the programmer’s responsibility to ensure this. If a predicate is promised pure or semipure and is not, the behaviour of the program is undefined.
The programmer may promise that a predicate or function is pure or semipure
:- pragma promise_pure(Name/Arity). :- pragma promise_semipure(Name/Arity).
Programmers should be very careful about mixing code that is promised pure with impure predicates or functions that may manipulate the same hidden state (for example, the impure predicates used to implement a predicate that is promised pure); the ‘promise_pure’ declaration is supposed to promise that impure code cannot change the declarative semantics of pure code. The module system can be used to minimize the possibility of making errors with such code, by keeping impure predicates or functions behind the interface where code is promised pure.
Note that the ‘promise_pure’, ‘promise_semipure’, and ‘promise_impure’ scopes described in Goals may be used to promise purity at the finer level of goals within clauses.