Std#
Ltac2.Std
Applying theorems#
val assumption : ?e:bool -> unit -> unit Proofview.tacticassumption () looks in the local context for a hypothesis whose type is convertible to the goal. If it is the case, the subgoal is proved. Otherwise, it fails.
val apply :
?e:bool ->
?in_hyp_as:(ident * Syntax.simple Syntax.intropattern option) ->
Syntax.constr_with_bindings list ->
unit Proofview.tacticapply ?e ts ?in_hyp_as uses unification to match the type of each t with the goal (to do backward reasoning) or with a hypothesis (to do forward reasoning). Specifying multiple constr_with_bindings is equivalent to giving each one serially, left to right, as separate apply tactics.
Managing the local context#
val intro :
?name:ident ->
?where:Syntax.move_location ->
unit ->
unit Proofview.tacticintro ?name ?where () introduces an item in the context by removing certain constructs in the goal. If no item is found, the tactic fails.
val intros :
?e:bool ->
Syntax.any Syntax.intropattern list ->
unit Proofview.tacticintros ?e patterns introduces a list of new variables in the context using the patterns. If patterns is empty, the tactic introduces items until it reaches the head constant; it never fails and may leave the context unchanged.
val intros_until : Syntax.hypothesis -> unit Proofview.tacticval revert : ident list -> unit Proofview.tacticrevert hyps moves the specified hypotheses and local definitions to the goal, if this respects dependencies. This is the inverse of intros.
val move : ident -> Syntax.move_location -> unit Proofview.tacticmove hyp where moves hyp and hypotheses that directly or indirectly refer to hyp that appear between hyp and where.
val clear : ident list -> unit Proofview.tacticclear hyps erases unneeded hypotheses in hyps from the context of the current goal. "Unneeded" means that the unselected hypotheses and the goal don't refer directly or indirectly to the erased hypotheses. That means the hypotheses will no longer appear in the context and therefore can't be used in subsequent proof steps. Note that erasing an unneeded hypothesis may turn a goal that was provable into an unprovable goal.
val keep : ident list -> unit Proofview.tactickeep hyps is the converse of clear, keeping only needed hypotheses in hyps.
val clearbody : ident list -> unit Proofview.tacticclearbody hyps clears the body of the given hyps in the context of the current goal.
val rename : (ident * ident) list -> unit Proofview.tacticrename l simultaneously renames hypotheses from the first name to the second.
val set :
?e:bool ->
?where:Syntax.clause ->
Names.Name.t ->
constr ->
unit Proofview.tacticset ?e name t ?where adds a new local definition name := t and replaces the body expression with the new variable name in the goal, or as specified by where.
val remember :
?e:bool ->
?as_name:ident ->
?eqn:Syntax.naming Syntax.intropattern ->
?where:Syntax.clause ->
constr ->
unit Proofview.tacticremember ?e t ?as_name ?eqn ?where is similar to set ?e as_name t ?where but creates a hypothesis using Leibniz equality to remember the relation between the introduced variable and the term rather than creating a local definition. If as_name is not specified, a fresh name is used. Use eqn to name the new equation.
val pose : Names.Name.t -> constr -> unit Proofview.tacticpose name t is similar to set name t, but does not perform any replacements.
Note: this version of pose does not fail on uninstantiated existential variables. To make it behave like Ltac's pose, use Control.with_holes.
Controlling the proof flow#
val assert_ :
?as_pattern:Syntax.simple Syntax.intropattern ->
?by:unit Proofview.tactic ->
constr ->
unit Proofview.tacticassert_ t ?as_pattern ?by adds a new hypothesis to the current subgoal and a new subgoal before it to prove the hypothesis.
Note: this version of assert does not fail on uninstantiated existential variables. To make it behave like Ltac's assert, use Control.with_holes.
val enough :
?as_pattern:Syntax.simple Syntax.intropattern ->
?by:unit Proofview.tactic ->
constr ->
unit Proofview.tacticenough t ?as_pattern ?by adds a new hypothesis to the current subgoal and a new subgoal after it to prove the hypothesis.
val cut : constr -> unit Proofview.tacticcut P transforms the current goal G into two subgoals: P -> G and P. This is the cut rule: to prove G, it suffices to prove that P implies G and that P itself holds.
This tactic is generally considered obsolete but it is still widely used in old scripts.
val specialize :
?as_pattern:Syntax.simple Syntax.intropattern ->
Syntax.constr_with_bindings ->
unit Proofview.tacticspecialize t ?as_pattern specializes t (typically a hypothesis or lemma) by applying arguments to it.
val generalize :
(constr * int Syntax.occurrences * Names.Name.t) list ->
unit Proofview.tacticgeneralize [(t, where, x)] replaces the goal G with forall (x: T), G', where t is a subterm of G of type T, and G' is obtained by replacing all occurrences of t with x within G. Specifying multiple t is equivalent to generalize t₁; …; generalize tₙ.
val absurd : constr -> unit Proofview.tacticabsurd P applies False elimination, that is, it deduces the current goal from False, and generates as subgoals ~P and P. It is very useful in proofs by cases, where some cases are impossible. In most cases, P or ~P is one of the hypotheses of the local context.
val contradiction :
?witness:Syntax.constr_with_bindings ->
unit ->
unit Proofview.tacticcontradiction ?witness () tries to prove the current goal by finding a contradiction.
If witness is not provided (the most common use case), the tactic first does an intros. The tactic then proves the goal if
- The updated context has a pair of hypotheses where one is the negation of the other (e.g.,
Pand~P), or - There is a hypothesis with an empty inductive type (e.g.,
False), or - There is a hypothesis
~PwherePis a singleton inductive type (e.g.,Trueorx=x) provable byconstructor.
val exfalso : unit Proofview.tacticImplements the "ex falso quodlibet" logical principle: an elimination of False is performed on the current goal, and the user is then required to prove that False is indeed provable in the current context.
val admit : unit Proofview.tacticAdmits the current goal. This marks the current goal as an axiom and closes it, leaving the proof incomplete. Useful for debugging or for temporarily accepting unprovable goals.
Performance-oriented tactic variants#
val exact_no_check : constr -> unit Proofview.tacticFor advanced usage. exact_no_check t is similar to exact t, but as an optimization, it skips checking that t has the goal's type, relying on the kernel check instead.
val vm_cast_no_check : constr -> unit Proofview.tacticFor advanced usage. vm_cast_no_check t is similar to exact_no_check t, but additionally instructs the kernel to use vm_compute to compare the goal's type with t's type.
val native_cast_no_check : constr -> unit Proofview.tacticFor advanced usage. native_cast_no_check t is similar to exact_no_check t, but additionally instructs the kernel to use native_compute to compare the goal's type with t's type.
Reasoning with equalities#
Tactics for simple equalities#
val reflexivity : unit Proofview.tacticAfter doing an intros, if the resulting goal is in the form t = u in which t and u are definitionally equal, the tactic proves the goal (by applying eq_refl). If not, it fails.
val symmetry : ?where:Syntax.clause -> unit -> unit Proofview.tacticChanges a goal that has the form forall x₀ … xₙ, t = u into u = t.
val transitivity : constr -> unit Proofview.tactictransitivity x changes a goal that has the form forall x₀ … xₙ, t = u into the two subgoals t = x and x = u.
val etransitivity : unit Proofview.tacticetransitivity behaves like transitivity, using a fresh evar instead of a concrete term.
val f_equal : unit Proofview.tacticFor a goal with the form f a₁ … aₙ = g b₁ … bₙ, creates subgoals f = g and aᵢ = bᵢ for the n arguments. Subgoals that can be proven by reflexivity or congruence are solved automatically.
Rewriting with Leibniz and setoid equality#
val rewrite :
?e:bool ->
?where:Syntax.clause ->
?by:unit Proofview.tactic ->
Syntax.oriented_rewriter list ->
unit Proofview.tacticrewrite rs ?e ?where ?by replaces subterms with other subterms that have been proven to be equal or logically equivalent.
val setoid_rewrite :
?orient:Syntax.orientation Syntax.intropattern ->
?in_hyp:ident ->
Syntax.constr_with_bindings ->
int Syntax.occurrences ->
unit Proofview.tacticsetoid_rewrite ?orient ?in_hyp c occs rewrites an occurrence of the term matched by c in the goal or the specified hypothesis using a setoid equality. Unlike rewrite, this tactic works with relations registered through the generalized rewriting framework.
val subst : ?hyps:ident list -> unit -> unit Proofview.tacticsubst ?hyps substitutes each hypothesis id : x = t (or t = x) in the goal, replacing x by t everywhere. Only hypotheses of the form x = t or t = x where x is a variable are considered.
If hyps is not specified, performs substitution of all known equalities in the goal.
val change :
?pattern:pattern ->
?where:Syntax.clause ->
(constr Names.Id.Map.t -> constr) ->
unit Proofview.tacticchange ?pattern f cl finds subterms matching pattern in the selected hypotheses and/or conclusion specified by cl, and replaces them with f args where args are the matched subterms.
Applying conversion rules#
module Red : sig ... endval eval_in : Red.t -> Syntax.clause -> unit Proofview.tacticeval_in red cl performs the reduction specified by red in the selected hypotheses and/or conclusion specified by cl.
val eval : Red.t -> constr -> constr Proofview.tacticeval red c reduces the term c using the specified reduction red and returns the resulting term, without modifying the goal.
Reasoning with inductive types#
Applying constructors#
val constructor :
?e:bool ->
?n:int ->
?with_:Syntax.bindings ->
unit ->
unit Proofview.tacticconstructor ?e ?n ?with_ () applies the n-th constructor, if specified, or the first matching constructor to prove the current goal. Fails if no constructor applies.
val split : ?e:bool -> ?with_:Syntax.bindings -> unit -> unit Proofview.tacticsplit ?e ?with_ () proves a conjunction A /\ B or an iff A <-> B by splitting it into subgoals. For conjunction, the left conjunct becomes the first subgoal. Any bindings are applied to the constructor.
val left : ?e:bool -> ?with_:Syntax.bindings -> unit -> unit Proofview.tacticleft ?e ?with_ () proves a disjunctive goal A \/ B by selecting the left disjunct A, generating a subgoal for A. Any bindings are applied to the constructor.
val right : ?e:bool -> ?with_:Syntax.bindings -> unit -> unit Proofview.tacticright ?e ?with_ () proves a disjunctive goal A \/ B by selecting the right disjunct B, generating a subgoal for B. Any bindings are applied to the constructor.
Case analysis#
val destruct :
?e:bool ->
?using:Syntax.constr_with_bindings ->
Syntax.Induction_clause.t list ->
unit Proofview.tacticdestruct clauses ?e ?using performs case analysis on each clause in clauses, generating a subgoal for each of the constructors of the inductive type.
val case : ?e:bool -> Syntax.constr_with_bindings -> unit Proofview.tacticcase c ?e is an older, more basic tactic to perform case analysis without recursion. We recommend using destruct instead where possible. case only modifies the goal; it does not modify the local context.
Induction#
val induction :
?e:bool ->
?using:Syntax.constr_with_bindings ->
Syntax.Induction_clause.t list ->
unit Proofview.tacticinduction clauses ?e ?using applies induction principles to each clause in clauses, left to right.
val elim :
?e:bool ->
?using:Syntax.constr_with_bindings ->
Syntax.constr_with_bindings ->
unit Proofview.tacticval fix : ident -> int -> unit Proofview.tacticval cofix : ident -> unit Proofview.tacticcofix f starts a proof by coinduction.
Equality of inductive types#
val discriminate :
?e:bool ->
?arg:Syntax.Induction_arg.t ->
unit ->
unit Proofview.tacticdiscriminate ?e ?arg () proves the current goal by discriminating an equality between two constructors of the same inductive type. The argument arg specifies which hypothesis or term to discriminate.
val injection :
?e:bool ->
?arg:Syntax.Induction_arg.t ->
?as_patterns:Syntax.simple Syntax.intropattern list ->
unit ->
unit Proofview.tacticinjection ?e ?as_patterns ?arg () exploits the property that constructors of inductive types are injective, i.e., that if c is a constructor of an inductive type, then c t1 = c t2 implies t1 = t2.
val inversion :
?kind:Syntax.inversion_kind ->
?as_pattern:Syntax.or_and Syntax.intropattern ->
?in_hyps:ident list ->
Syntax.Induction_arg.t ->
unit Proofview.tacticinversion ?kind arg ?as_pattern ?in_hyps performs inversion on the given term arg using the specified kind of inversion. Inversion generates equations for all constructors of the inductive type of arg and proves the goal by case analysis.
Solvers for logic and equality#
val congruence : ?n:int -> ?hints:constr list -> unit -> unit Proofview.tacticcongruence ?n ?hints () solves the current goal using the congruence closure algorithm, which reasons about equations between constructors and function applications.
val simple_congruence :
?n:int ->
?hints:constr list ->
unit ->
unit Proofview.tacticsimple_congruence ?n ?hints () behaves like congruence but does not unfold definitions.
Programmable proof search#
Controls whether debug information is printed or not.
See Hints.debug.
Controls which strategy to use for proof search.
val auto :
?debug:debug ->
?n:int ->
?dbs:ident list ->
reference list ->
unit Proofview.tacticauto refs ?debug ?n ?dbs applies the auto proof search algorithm with backtracking, which tries to solve the goal by applying hints from the specified databases.
val eauto :
?debug:debug ->
?n:int ->
?dbs:ident list ->
reference list ->
unit Proofview.tacticeauto refs ?debug ?n ?dbs applies the eauto proof search algorithm, which extends auto with unification hints and e-unification.
val typeclasses_eauto :
?strategy:strategy ->
?n:int ->
?dbs:ident list ->
unit ->
unit Proofview.tactictypeclasses_eauto ?strategy ?n ?dbs () applies typeclass resolution using the specified search strategy. Typeclass resolution is a form of automated proof search specialized for typeclass instance resolution.
val autorewrite :
all:bool ->
?forward:bool ->
?where:Syntax.clause ->
?using:unit Proofview.tactic ->
ident list ->
unit Proofview.tacticautorewrite ~all ?forward ?where ?using dbs rewrites in the goal using the rewrite rules registered in the specified hint databases dbs.
val trivial :
?debug:debug ->
?dbs:ident list ->
reference list ->
unit Proofview.tactictrivial refs ?debug ?dbs behaves like auto, but is not recursive and only tries hints with zero cost. Typically used to solve goals for which a lemma is already available in the specified hint databases.
Misc#
val resolve_tc : constr -> unit Proofview.tacticresolve_tc c resolves the existential variables appearing in the constr whose types are typeclasses. Fails if they cannot be resolved. Does not focus.
val unify : constr -> constr -> unit Proofview.tacticunify x y checks that x and y are convertible (definitionally equal) in the current context. Fails if they are not unifiable.