6.2.901.900
3.1 Tactics
As Coq has shown, tactics have proven useful for doing complex proofs. In Cur, tactics are not
built-in or provided by the language. However, any user can use meta-programming to add tactics to
Cur. A tactic system ships in the standard library, written entirely in user-land code.
3.1.1 Proof State and Defining Tactics
(define-tactic (name id ... id-ps))
|
(define-tactic name procedure-expr) |
Defines a new
tactic, at
phase 1. A
tactic is a Racket function from
proof state to
proof state that runs at
phase 1. A
tactic takes any
number of arguments, plus the
proof state. The
proof state must be the final argument of
the tactic.
Examples: |
> (define-tactic (do-nothing ps) | ps) |
| > (define-tactic (switch-goal i ps) | (struct-copy proof-state ps | [current-goal i])) |
|
|
(proof? p) → boolean?
|
p : any/c |
Returns
#t if
p is a proof, and
#f otherwise.
A
proof is either a Cur term as a syntax object, or a procedure expecting a proof to plug
into the holes of the existing partial proof.
(complete-proof? p) → boolean?
|
p : any/c |
Returns #t is the proof p has no holes, i.e., is a syntax object, and #f
otherwise.
Returns an empty partial
proof, i.e., the identity function.
(struct | | proof-state (env goals current-goal proof theorem) |
|
#:extra-constructor-name make-proof-state) |
env : dict? |
goals : dict? |
current-goal : natural-number/c |
proof : (or/c syntax? procedure?) |
theorem : syntax? |
The environment
env is a map of assumptions local to the theorem from symbols (names) to the
type of the assumption as a syntax object.
The list of goals
goals is a map from natural numbers to goals, types as syntax objects.
The current goal
current-goal is a natural number indexing into
goals, representing
the goal currently in focus.
The
proof is the
proof of the theorem so far. The
proof is either a
syntax object if complete, or a procedure which expects a proof to replace the current holes in the
proof.
The
theorem is the original statement of the theorem to be proved.
(new-proof-state prop) → proof-state?
|
prop : syntax? |
Returns a proof-state? initialized with an empty environment, the list of goals initialized with
prop, the current-goal set to 0, an empty proof via (new-proof), and the
theorem set to prop.
(proof-state-proof-complete? ps) → boolean?
|
ps : proof-state? |
Returns #t is the proof of the proof-state? ps is a
complete-proof?, and #f otherwise.
(proof-state-goal-ref ps i) → syntax?
|
ps : proof-sate? |
i : natural-number/c |
Returns the ith goal from the proof state ps.
(proof-state-current-goal-ref ps) → syntax?
|
ps : proof-state? |
Returns the goal using the index from
(proof-state-current-goal ps).
(proof-state-env-ref ps name) → syntax?
|
ps : proof-state? |
name : symbol? |
Returns the type of the assumption name in the local
environment of ps.
(proof-state-env-ref-by-type ps type) → (or/c symbol? #f)
|
ps : proof-state? |
type : syntax? |
Returns the name of the assumption of type type from the local
environment of ps, or #f is no
assumption with type exists.
(proof-state-extend-env ps name type) → proof-state?
|
ps : proof-state? |
name : (or/c symbol? identifier?) |
type : syntax? |
Returns a proof state with the local environment of
ps updated to include the assumption name of type
type.
(proof-state-current-goal-set ps goal) → proof-state?
|
ps : proof-state? |
goal : syntax? |
Returns a proof state with the current goal in the goals list of
ps changed to goal.
(proof-state-fill-proof-hole ps pf) → proof-state?
|
ps : proof-state? |
pf : proof? |
Returns a proof state with the current holes of the proof filled with
pf.
(proof-state-extend-proof-context ps ctxt) → proof-state?
|
ps : proof-state? |
ctxt : procedure? |
Updates the proof in ps by playing the current proof inside the
holes of ctxt.
(print-proof-state ps) → void?
|
ps : proof-state? |
Pretty-prints ps to the current-output-port.
(lookup-tactic name) → procedure?
|
name : (or/c symbol? identifier?) |
Returns the tactic defined with name name. Only works when the
tactic is defined and a theorem has been defined but not proved.
(define-theorem name prop)
|
Defines a new theorem.
(proof (tactic args ...) ...)
|
Proves the theorem previously defined with define-theorem. Currently, this proof is not
saved anywhere, only checked against the most recent theorem defined via define-theorem.
Note that the proof state is implicitly given to each call by proof and should not appear as
an explicit argument.
Examples: |
> (define-theorem a-silly-theorem (forall (x : Nat) Nat)) | > (proof (intro x) (by-assumption)) | '(λ (x1 : Nat) x1) | > (define-theorem falseo (forall (x : Type) x)) | > (proof (interactive)) |
|
TODO: Examples, better documentation (e.g. don’t say "returns a proof state"; the signature says so)
3.1.2 Standard Tactics
The tactic system includes several standard tactics.
(intro name ps) → proof-state?
|
name : identifier? |
ps : proof-state? |
Matches when the current goal has the form (forall (id : type-expr) body-expr), introducing
the assumption id : type-expr into the local environment of ps.
(by-assumption ps) → proof-state?
|
ps : proof-state? |
Matches with the current goal has a type that matches an assumption in the local environment of
ps. Completes the goal.
(obvious ps) → proof-state?
|
ps : proof-state? |
Attempts to prove the current goal by doing the obvious thing.
(restart ps) → proof-state?
|
ps : proof-state? |
Resets ps to its state when the proof began. Clears the proof and goals, reinitializing the
goals to the original theorem.
(print ps) → proof-state?
|
ps : proof-state? |
Prints ps, returning it unmodified.
(forget x ps) → proof-state?
|
x : identifier? |
ps : proof-state? |
Removes the assumption x from the local environment of ps.
3.1.3 Interactive Tactic
In Cur, interactivity is just a user-defined tactic.
(interactive ps) → proof-state?
|
ps : proof-state? |
Starts a REPL that prints ps, reads a tactic (as proof would), evaluates the
tactic, and repeats. To quit, use (quit).
3.1.4 SarTactic (Sarcastic Tactics)
The SarTactic library provides amusing wrappers around the standard tactics. This library exists
mostly for the author’s own amusement, and to ensure the extensibility of the tactic system.
It defines the same tactics as cur/stdlib/tactics/standard, but each tactics will
insult the user, and will only work some of the time.