Harpoon is an interactive proof assistant for Beluga. It aims to make proving in Beluga simpler by streamlining proofs into a small set of tactics. Instead of fretting over the syntax of Beluga terms, the programmer can instead focus on the formulas being manipulated.
Start the Harpoon interactive mode by using bin/harpoon --implicit --sig SIG where SIG
is the name of the signature file you will use as a context of your theorem.
A Harpoon instance is broken up into a hierarchical structure:
- A session consists of multiple theorems being proven mutually.
- A theorem consists of multiple open subgoals that must be solved.
- A subgoal is the basic unit of work in Harpoon, and all proper tactics affect the currently active subgoal.
When Harpoon starts, it runs the session configuration wizard, with which you interactively configure the theorems to prove in the default session. For each theorem, you must provide:
- The name of the theorem. To finish configuration, leave an empty name and press the return key.
- The statement of the theorem. This is a Beluga type, subject to automatic
abstraction for implicit parameters,
e.g.
[|- oft M A] -> [|- eval M M'] -> [|- oft M' A]will have the free (meta)variablesM,A, andM'universally quantified. - The termination measure for the theorem. Currently, Beluga only supports
structural recursion on a single argument. This argument is specified by
number in this prompt. For type preservation, we proceed by induction on the
evaluation judgment, which is the second argument to the theorem, so you would
write
2for the termination measure. In other words, the 1-indexed argument number is given without counting implicit arguments.
With session configuration finished, the main Harpoon prompt appears.
Harpoon operates internally on a list of open subgoals. The Harpoon prompt is presented in the context of a current subgoal, theorem, and session: all computational and metavariables will be listed along with their types. Initially, the only subgoal is the whole theorem, with all the assumptions introduced. (See the section Automatic Tactics for why.)
These are commands that do not advance the proof, but instead serve to manage the current proof and the proof assistant.
rename: rename a variable.toggle-automation KIND: enables/disables the automatic tacticKIND. Supported values ofKINDare:auto-intros,auto-solve-trivial. These are described in the section Automatic Tacticstype E: show the type of the (synthesizable) expressionE.
All remaining administrative commands are broken up according to whether they affect the active session, theorem, or subgoal.
session COMMANDaffects the current session. The following options are possible forCOMMAND:defer: switch to the next session.list: list all sessions.select NAME: select a session by name.create NAME: create a new session with the given name.
theorem COMMANDaffects the current theorem. The following options are possible forCOMMAND:defer,list,select NAME: behave as forsession.show-ihs: list available induction hypotheses.show-proof: display theorem's (partial) proof script.
subgoal COMMAND: affects the current subgoal. The following options are possible forCOMMAND:defer,list: same as fortheoremandsession.
Since deferring the current subgoal is the most common type of defer, the
toplevel command defer is a shortcut for subgoal defer.
The following are the proof tactics. In these commands, E denotes a
computational expression.
intros [NAMES...]: introduces the assumptions of the current subgoal. Explicit names can be optionally given to the assumptions. If no names are specified, then names are generated automatically.split E: perform case analysis on the expressionE. The current subgoal is eliminated and one new subgoal is generated for every case.invert E: identical tosplit, but it is checked that there is exactly one case.impossible E: identical tosplit, but it is checked that there are exactly zero cases.unbox E as X: assumingEis of box-type, defines a metavariableXwith the same type.by C E as x [unboxed]: invoke the expressionEand bind the result as the variablex. If theunboxedkeyword is given, then the variablexis a new metavariable (in the meta-context); else,xis a new computational variable. Choices forCare:ihandlemma. e.g. if we are provingtps, then we may want to invoke the induction hypothesis asby ih tps [|- D] [|- E] as r.suffices by C E toshow T_1, T_2, ..., T_(n-1): The ordinarybycommand is a forward reasoning tactic, whereassuffices byis a backward reasoning tactic.- Currently, the only supported invocation kind
Cislemma. - The expression
Emust synthesize a type of the form:{X_1 : U_1} {X_2 : U_2} ... {X_k : U_k} T_1' -> T_2' -> ... -> T_n' - The given types
T_imust unify with the correspondingT_i'. - The current goal type must unify with
T_n'. - The unification must instantiate all universally quantified variables
X_j. The current subgoal is removed, and one subgoal is added for each of the types given aftertoshow. For example, suppose that the current subgoal is[|- eq A A]forA : [|- tp]; we must prove that thatAis equal to itself. Suppose further that we have the lemmarefl : {X : [|- tp]} [|- eq X X]. The goal can be solved by usingsuffices by lemma refl toshow.[|- eq X X]will be unified with[|- eq A A], instantiating the (only) universally quantified variableX := A. There are no subgoals introduced since the lemma has no premises.
- Currently, the only supported invocation kind
solve E: solve the current subgoal with the expressionE.
Some tactics in Harpoon can be performed eagerly without affecting the
provability of the goal. Whenever a new subgoal is created, Harpoon will
automatically apply these tactics, subject to whether they are enabled.
(See the section Harpoon Commands for the description of the
toggle-automation command.)
The following are the available automatic tactics.
auto-intros: subgoals will automatically have all assumptions introduced with automatically generated names.auto-solve-trivial: trivial subgoals will be solved automatically. A subgoal is trivial if the goal is present as an assumption.