Explanation of the
By default, the define-sk macro handles calls of
Note: you can disable this behavior via
Consider a quantified function definition like:
(defun-sk all-greaterp (min list) (declare (xargs :guard (and (integerp min) (integer-listp list)) :verify-guards nil)) (forall (elem) (implies (member elem list) (< min elem))))
Unfortunately, the above produces a lousy
(defthm all-greaterp-necc (implies (not (implies (member elem list) (< min elem))) (not (all-greaterp min list))))
We can get a better rule by adding the
(defthm all-greaterp-necc (implies (all-greaterp min list) (implies (member elem list) (< min elem))))
So that's great. The problem comes in when we try to verify the guards of
To fix this, we might try to rewrite our function to get rid of the
(defun-sk all-greaterp (min list) (declare (xargs :guard (and (integerp min) (integer-listp list)) :verify-guards nil)) (forall (elem) (if (member elem list) (< min elem) t)) :rewrite :direct)
But now we run into a different problem: the
(defthm all-greaterp-necc (implies (all-greaterp min list) (if (member elem list) (< min elem) t)))
But this isn't a valid
In short: for guard verification we generally want to use something like
To try to help with this, define-sk does something special with
(define-sk all-greaterp ((min integerp) (list integer-listp)) (forall (elem) (implies (member elem list) (< min elem))))
The
(defun all-greaterp (min list) (declare ...) (let ((elem (all-greaterp-witness min list))) (if (member elem list) (< min elem) t)))
This will generally help to make guard verification more straightforward
because you'll be able to assume the hyps hold during the conclusion. But note
that this rewriting of
Is this safe? There's of course no logical difference between