as_aux_lemma => tac does the same as tac, except that it wraps the resulting expression
into an auxiliary lemma. In some cases, this significantly reduces the size of expressions
because the proof term is not duplicated.
Equations
- One or more equations did not get rendered due to their size.
Instances For
with_annotate_state stx t annotates the lexical range of stx : Syntax with
the initial and final state of running tactic t.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Introduces one or more hypotheses, optionally naming and/or pattern-matching them.
For each hypothesis to be introduced, the remaining main goal's target type must
be a let or function type.
introby itself introduces one anonymous hypothesis, which can be accessed by e.g.assumption. It is equivalent tointro _.intro x yintroduces two hypotheses and names them. Individual hypotheses can be anonymized via_, given a type ascription, or matched against a pattern:-- ... ⊢ α × β → ... intro (a, b) -- ..., a : α, b : β ⊢ ...intro rflis short forintro h; subst h, ifhis an equality where the left-hand or right-hand side is a variable.- Alternatively,
introcan be combined with pattern matching much likefun:intro | n + 1, 0 => tac | ...
Equations
- One or more equations did not get rendered due to their size.
Instances For
intros repeatedly applies intro to introduce zero or more hypotheses
until the goal is no longer a binding expression
(i.e., a universal quantifier, function type, implication, or have/let),
without performing any definitional reductions (no unfolding, beta, eta, etc.).
The introduced hypotheses receive inaccessible (hygienic) names.
intros x y z is equivalent to intro x y z and exists only for historical reasons.
The intro tactic should be preferred in this case.
Properties and relations #
introssucceeds even when it introduces no hypotheses.repeat introis likeintros, but it performs definitional reductions to expose binders, and as such it may introduce more hypotheses thanintros.introsis equivalent tointro _ _ … _, with the fewest trailing_placeholders needed so that the goal is no longer a binding expression. The trailing introductions do not perform any definitional reductions.
Examples #
Implications:
example (p q : Prop) : p → q → p := by
intros
/- Tactic state
a✝¹ : p
a✝ : q
⊢ p -/
assumption
Let-bindings:
example : let n := 1; let k := 2; n + k = 3 := by
intros
/- n✝ : Nat := 1
k✝ : Nat := 2
⊢ n✝ + k✝ = 3 -/
rfl
Does not unfold definitions:
def AllEven (f : Nat → Nat) := ∀ n, f n % 2 = 0
example : ∀ (f : Nat → Nat), AllEven f → AllEven (fun k => f (k + 1)) := by
intros
/- Tactic state
f✝ : Nat → Nat
a✝ : AllEven f✝
⊢ AllEven fun k => f✝ (k + 1) -/
sorry
Equations
- One or more equations did not get rendered due to their size.
Instances For
rename t => x renames the most recent hypothesis whose type matches t
(which may contain placeholders) to x, or fails if no such hypothesis could be found.
Equations
- One or more equations did not get rendered due to their size.
Instances For
clear x... removes the given hypotheses, or fails if there are remaining
references to a hypothesis.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Syntax for trying to clear the values of all local definitions.
Equations
- Lean.Parser.Tactic.clearValueStar = Lean.ParserDescr.nodeWithAntiquot "clearValueStar" `Lean.Parser.Tactic.clearValueStar (Lean.ParserDescr.symbol "*")
Instances For
Syntax for creating a hypothesis before clearing values.
In (hx : x = _), the value of x is unified with _.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Argument for the clear_value tactic.
Equations
- One or more equations did not get rendered due to their size.
Instances For
clear_value x...clears the values of the given local definitions. A local definitionx : α := vbecomes a hypothesisx : α.clear_value (h : x = _)adds a hypothesish : x = vbefore clearing the value ofx. This is short forhave h : x = v := rfl; clear_value x. Any value definitionally equal tovcan be used in place of_.clear_value *clears values of all hypotheses that can be cleared. Fails if none can be cleared.
These syntaxes can be combined. For example, clear_value x y * ensures that x and y are cleared
while trying to clear all other local definitions,
and clear_value (hx : x = _) y * with hx does the same while first adding the hx : x = v hypothesis.
Equations
- One or more equations did not get rendered due to their size.
Instances For
subst x... substitutes each hypothesis x with a definition found in the local context,
then eliminates the hypothesis.
- If
xis a local definition, then its definition is used. - Otherwise, if there is a hypothesis of the form
x = eore = x, theneis used for the definition ofx.
If h : a = b, then subst h may be used if either a or b unfolds to a local hypothesis.
This is similar to the cases h tactic.
See also: subst_vars for substituting all local hypotheses that have a defining equation.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Applies subst to all hypotheses of the form h : x = t or h : t = x.
Equations
- Lean.Parser.Tactic.substVars = Lean.ParserDescr.node `Lean.Parser.Tactic.substVars 1024 (Lean.ParserDescr.nonReservedSymbol "subst_vars" false)
Instances For
assumption tries to solve the main goal using a hypothesis of compatible type, or else fails.
Note also the ‹t› term notation, which is a shorthand for show t by assumption.
Equations
- Lean.Parser.Tactic.assumption = Lean.ParserDescr.node `Lean.Parser.Tactic.assumption 1024 (Lean.ParserDescr.nonReservedSymbol "assumption" false)
Instances For
contradiction closes the main goal if its hypotheses are "trivially contradictory".
- Inductive type/family with no applicable constructors
example (h : False) : p := by contradiction - Injectivity of constructors
example (h : none = some true) : p := by contradiction -- - Decidable false proposition
example (h : 2 + 2 = 3) : p := by contradiction - Contradictory hypotheses
example (h : p) (h' : ¬ p) : q := by contradiction - Other simple contradictions such as
example (x : Nat) (h : x ≠ x) : p := by contradiction
Equations
- Lean.Parser.Tactic.contradiction = Lean.ParserDescr.node `Lean.Parser.Tactic.contradiction 1024 (Lean.ParserDescr.nonReservedSymbol "contradiction" false)
Instances For
Changes the goal to False, retaining as much information as possible:
- If the goal is
False, do nothing. - If the goal is an implication or a function type, introduce the argument and restart.
(In particular, if the goal is
x ≠ y, introducex = y.) - Otherwise, for a propositional goal
P, replace it with¬ ¬ P(attempting to find aDecidableinstance, but otherwise falling back to working classically) and introduce¬ P. - For a non-propositional goal use
False.elim.
Equations
- Lean.Parser.Tactic.falseOrByContra = Lean.ParserDescr.node `Lean.Parser.Tactic.falseOrByContra 1024 (Lean.ParserDescr.nonReservedSymbol "false_or_by_contra" false)
Instances For
apply e tries to match the current goal against the conclusion of e's type.
If it succeeds, then the tactic returns as many subgoals as the number of premises that
have not been fixed by type inference or type class resolution.
Non-dependent premises are added before dependent ones.
The apply tactic uses higher-order pattern matching, type class resolution,
and first-order unification with dependent types.
Equations
- One or more equations did not get rendered due to their size.
Instances For
exact e closes the main goal if its target type matches that of e.
Equations
- One or more equations did not get rendered due to their size.
Instances For
refine e behaves like exact e, except that named (?x) or unnamed (?_)
holes in e that are not solved by unification with the main goal's target type
are converted into new goals, using the hole's name, if any, as the goal case name.
Equations
- One or more equations did not get rendered due to their size.
Instances For
exfalso converts a goal ⊢ tgt into ⊢ False by applying False.elim.
Equations
- Lean.Parser.Tactic.tacticExfalso = Lean.ParserDescr.node `Lean.Parser.Tactic.tacticExfalso 1024 (Lean.ParserDescr.nonReservedSymbol "exfalso" false)
Instances For
If the main goal's target type is an inductive type, constructor solves it with
the first matching constructor, or else fails.
Equations
- Lean.Parser.Tactic.constructor = Lean.ParserDescr.node `Lean.Parser.Tactic.constructor 1024 (Lean.ParserDescr.nonReservedSymbol "constructor" false)
Instances For
Applies the first constructor when the goal is an inductive type with exactly two constructors, or fails otherwise.
example : True ∨ False := by
left
trivial
Equations
- Lean.Parser.Tactic.left = Lean.ParserDescr.node `Lean.Parser.Tactic.left 1024 (Lean.ParserDescr.nonReservedSymbol "left" false)
Instances For
Applies the second constructor when the goal is an inductive type with exactly two constructors, or fails otherwise.
example {p q : Prop} (h : q) : p ∨ q := by
right
exact h
Equations
- Lean.Parser.Tactic.right = Lean.ParserDescr.node `Lean.Parser.Tactic.right 1024 (Lean.ParserDescr.nonReservedSymbol "right" false)
Instances For
case tag => tacfocuses on the goal with case nametagand solves it usingtac, or else fails.case tag x₁ ... xₙ => tacadditionally renames thenmost recent hypotheses with inaccessible names to the given names.case tag₁ | tag₂ => tacis equivalent to(case tag₁ => tac); (case tag₂ => tac).
Equations
- One or more equations did not get rendered due to their size.
Instances For
case' is similar to the case tag => tac tactic, but does not ensure the goal
has been solved after applying tac, nor admits the goal if tac failed.
Recall that case closes the goal using sorry when tac fails, and
the tactic execution is not interrupted.
Equations
- One or more equations did not get rendered due to their size.
Instances For
next => tac focuses on the next goal and solves it using tac, or else fails.
next x₁ ... xₙ => tac additionally renames the n most recent hypotheses with
inaccessible names to the given names.
Equations
- One or more equations did not get rendered due to their size.
Instances For
all_goals tac runs tac on each goal, concatenating the resulting goals.
If the tactic fails on any goal, the entire all_goals tactic fails.
See also any_goals tac.
Equations
- One or more equations did not get rendered due to their size.
Instances For
any_goals tac applies the tactic tac to every goal,
concatenating the resulting goals for successful tactic applications.
If the tactic fails on all of the goals, the entire any_goals tactic fails.
This tactic is like all_goals try tac except that it fails if none of the applications of tac succeeds.
Equations
- One or more equations did not get rendered due to their size.
Instances For
focus tac focuses on the main goal, suppressing all other goals, and runs tac on it.
Usually · tac, which enforces that the goal is closed by tac, should be preferred.
Equations
- One or more equations did not get rendered due to their size.
Instances For
skip does nothing.
Equations
- Lean.Parser.Tactic.skip = Lean.ParserDescr.node `Lean.Parser.Tactic.skip 1024 (Lean.ParserDescr.nonReservedSymbol "skip" false)
Instances For
done succeeds iff there are no remaining goals.
Equations
- Lean.Parser.Tactic.done = Lean.ParserDescr.node `Lean.Parser.Tactic.done 1024 (Lean.ParserDescr.nonReservedSymbol "done" false)
Instances For
trace_state displays the current state in the info view.
Equations
- Lean.Parser.Tactic.traceState = Lean.ParserDescr.node `Lean.Parser.Tactic.traceState 1024 (Lean.ParserDescr.nonReservedSymbol "trace_state" false)
Instances For
trace msg displays msg in the info view.
Equations
- One or more equations did not get rendered due to their size.
Instances For
fail_if_success t fails if the tactic t succeeds.
Equations
- One or more equations did not get rendered due to their size.
Instances For
(tacs) executes a list of tactics in sequence, without requiring that
the goal be closed at the end like · tacs. Like by itself, the tactics
can be either separated by newlines or ;.
Equations
- One or more equations did not get rendered due to their size.
Instances For
with_reducible tacs executes tacs using the reducible transparency setting.
In this setting only definitions tagged as [reducible] are unfolded.
Equations
- One or more equations did not get rendered due to their size.
Instances For
with_reducible_and_instances tacs executes tacs using the .instances transparency setting.
In this setting only definitions tagged as [reducible] or type class instances are unfolded.
Equations
- One or more equations did not get rendered due to their size.
Instances For
with_unfolding_all tacs executes tacs using the .all transparency setting.
In this setting all definitions that are not opaque are unfolded.
Equations
- One or more equations did not get rendered due to their size.
Instances For
first | tac | ... runs each tac until one succeeds, or else fails.
Equations
- One or more equations did not get rendered due to their size.
Instances For
rotate_left n rotates goals to the left by n. That is, rotate_left 1
takes the main goal and puts it to the back of the subgoal list.
If n is omitted, it defaults to 1.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Rotate the goals to the right by n. That is, take the goal at the back
and push it to the front n times. If n is omitted, it defaults to 1.
Equations
- One or more equations did not get rendered due to their size.
Instances For
try tac runs tac and succeeds even if tac failed.
Equations
- One or more equations did not get rendered due to their size.
Instances For
tac <;> tac' runs tac on the main goal and tac' on each produced goal,
concatenating all goals produced by tac'.
Equations
- One or more equations did not get rendered due to their size.
Instances For
fail msg is a tactic that always fails, and produces an error using the given message.
Equations
- One or more equations did not get rendered due to their size.
Instances For
eq_refl is equivalent to exact rfl, but has a few optimizations.
Equations
- Lean.Parser.Tactic.eqRefl = Lean.ParserDescr.node `Lean.Parser.Tactic.eqRefl 1024 (Lean.ParserDescr.nonReservedSymbol "eq_refl" false)
Instances For
This tactic applies to a goal whose target has the form x ~ x,
where ~ is equality, heterogeneous equality or any relation that
has a reflexivity lemma tagged with the attribute @[refl].
Equations
- Lean.Parser.Tactic.tacticRfl = Lean.ParserDescr.node `Lean.Parser.Tactic.tacticRfl 1024 (Lean.ParserDescr.nonReservedSymbol "rfl" false)
Instances For
The same as rfl, but without trying eq_refl at the end.
Equations
- Lean.Parser.Tactic.applyRfl = Lean.ParserDescr.node `Lean.Parser.Tactic.applyRfl 1024 (Lean.ParserDescr.nonReservedSymbol "apply_rfl" false)
Instances For
rfl' is similar to rfl, but disables smart unfolding and unfolds all kinds of definitions,
theorems included (relevant for declarations defined by well-founded recursion).
Equations
- Lean.Parser.Tactic.tacticRfl' = Lean.ParserDescr.node `Lean.Parser.Tactic.tacticRfl' 1024 (Lean.ParserDescr.nonReservedSymbol "rfl'" false)
Instances For
ac_rfl proves equalities up to application of an associative and commutative operator.
instance : Std.Associative (α := Nat) (.+.) := ⟨Nat.add_assoc⟩
instance : Std.Commutative (α := Nat) (.+.) := ⟨Nat.add_comm⟩
example (a b c d : Nat) : a + b + c + d = d + (b + c) + a := by ac_rfl
Equations
- Lean.Parser.Tactic.acRfl = Lean.ParserDescr.node `Lean.Parser.Tactic.acRfl 1024 (Lean.ParserDescr.nonReservedSymbol "ac_rfl" false)
Instances For
The sorry tactic is a temporary placeholder for an incomplete tactic proof,
closing the main goal using exact sorry.
This is intended for stubbing-out incomplete parts of a proof while still having a syntactically correct proof skeleton.
Lean will give a warning whenever a proof uses sorry, so you aren't likely to miss it,
but you can double check if a theorem depends on sorry by looking for sorryAx in the output
of the #print axioms my_thm command, the axiom used by the implementation of sorry.
Equations
- Lean.Parser.Tactic.tacticSorry = Lean.ParserDescr.node `Lean.Parser.Tactic.tacticSorry 1024 (Lean.ParserDescr.nonReservedSymbol "sorry" false)
Instances For
admit is a synonym for sorry.
Equations
- Lean.Parser.Tactic.tacticAdmit = Lean.ParserDescr.node `Lean.Parser.Tactic.tacticAdmit 1024 (Lean.ParserDescr.nonReservedSymbol "admit" false)
Instances For
infer_instance is an abbreviation for exact inferInstance.
It synthesizes a value of any target type by typeclass inference.
Equations
- Lean.Parser.Tactic.tacticInfer_instance = Lean.ParserDescr.node `Lean.Parser.Tactic.tacticInfer_instance 1024 (Lean.ParserDescr.nonReservedSymbol "infer_instance" false)
Instances For
+opt is short for (opt := true). It sets the opt configuration option to true.
Equations
- One or more equations did not get rendered due to their size.
Instances For
-opt is short for (opt := false). It sets the opt configuration option to false.
Equations
- One or more equations did not get rendered due to their size.
Instances For
(opt := val) sets the opt configuration option to val.
As a special case, (config := ...) sets the entire configuration.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A configuration item for a tactic configuration.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Configuration options for tactics.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Optional configuration option for tactics. (Deprecated. Replace (config)? with optConfig.)
Equations
- One or more equations did not get rendered due to their size.
Instances For
The * location refers to all hypotheses and the goal.
Equations
- Lean.Parser.Tactic.locationWildcard = Lean.ParserDescr.nodeWithAntiquot "locationWildcard" `Lean.Parser.Tactic.locationWildcard (Lean.ParserDescr.symbol " *")
Instances For
The ⊢ location refers to the current goal.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A sequence of one or more locations at which a tactic should operate. These can include local
hypotheses and ⊢, which denotes the goal.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Location specifications are used by many tactics that can operate on either the hypotheses or the goal. It can have one of the forms:
- 'empty' is not actually present in this syntax, but most tactics use
(location)?matchers. It means to target the goal only. at h₁ ... hₙ: target the hypothesesh₁, ...,hₙat h₁ h₂ ⊢: target the hypothesesh₁andh₂, and the goalat *: target all hypotheses and the goal
Equations
- One or more equations did not get rendered due to their size.
Instances For
show t finds the first goal whose target unifies with t. It makes that the main goal,
performs the unification, and replaces the target with the unified version of t.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Extracts let and have expressions from within the target or a local hypothesis,
introducing new local definitions.
extract_letsextracts all the lets from the target.extract_lets x y zextracts all the lets from the target and usesx,y, andzfor the first names. Using_for a name leaves it unnamed.extract_lets x y z at hoperates on the local hypothesishinstead of the target.
For example, given a local hypotheses if the form h : let x := v; b x, then extract_lets z at h
introduces a new local definition z := v and changes h to be h : b z.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Lifts let and have expressions within a term as far out as possible.
It is like extract_lets +lift, but the top-level lets at the end of the procedure
are not extracted as local hypotheses.
lift_letslifts let expressions in the target.lift_lets at hlifts let expressions at the given local hypothesis.
For example,
example : (let x := 1; x) = 1 := by
lift_lets
-- ⊢ let x := 1; x = 1
...
Equations
- One or more equations did not get rendered due to their size.
Instances For
Transforms let expressions into have expressions when possible.
let_to_havetransformslets in the target.let_to_have at htransformslets in the given local hypothesis.
Equations
- One or more equations did not get rendered due to their size.
Instances For
If thm is a theorem a = b, then as a rewrite rule,
thmmeans to replaceawithb, and← thmmeans to replacebwitha.
Equations
- One or more equations did not get rendered due to their size.
Instances For
rewrite [e] applies identity e as a rewrite rule to the target of the main goal.
If e is preceded by left arrow (← or <-), the rewrite is applied in the reverse direction.
If e is a defined constant, then the equational theorems associated with e are used.
This provides a convenient way to unfold e.
rewrite [e₁, ..., eₙ]applies the given rules sequentially.rewrite [e] at lrewriteseat location(s)l, wherelis either*or a list of hypotheses in the local context. In the latter case, a turnstile⊢or|-can also be used, to signify the target of the goal.
Using rw (occs := .pos L) [e],
where L : List Nat, you can control which "occurrences" are rewritten.
(This option applies to each rule, so usually this will only be used with a single rule.)
Occurrences count from 1.
At each allowed occurrence, arguments of the rewrite rule e may be instantiated,
restricting which later rewrites can be found.
(Disallowed occurrences do not result in instantiation.)
(occs := .neg L) allows skipping specified occurrences.
Equations
- One or more equations did not get rendered due to their size.
Instances For
rw is like rewrite, but also tries to close the goal by "cheap" (reducible) rfl afterwards.
Equations
- One or more equations did not get rendered due to their size.
Instances For
rwa is short-hand for rw; assumption.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The injection tactic is based on the fact that constructors of inductive data
types are injections.
That means that if c is a constructor of an inductive datatype, and if (c t₁)
and (c t₂) are two terms that are equal then t₁ and t₂ are equal too.
If q is a proof of a statement of conclusion t₁ = t₂, then injection applies
injectivity to derive the equality of all arguments of t₁ and t₂ placed in
the same positions. For example, from (a::b) = (c::d) we derive a=c and b=d.
To use this tactic t₁ and t₂ should be constructor applications of the same constructor.
Given h : a::b = c::d, the tactic injection h adds two new hypothesis with types
a = c and b = d to the main goal.
The tactic injection h with h₁ h₂ uses the names h₁ and h₂ to name the new hypotheses.
Equations
- One or more equations did not get rendered due to their size.
Instances For
injections applies injection to all hypotheses recursively
(since injection can produce new hypotheses). Useful for destructing nested
constructor equalities like (a::b::c) = (d::e::f).
Equations
- One or more equations did not get rendered due to their size.
Instances For
The discharger clause of simp and related tactics.
This is a tactic used to discharge the side conditions on conditional rewrite rules.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Use this rewrite rule before entering the subterms
Equations
- Lean.Parser.Tactic.simpPre = Lean.ParserDescr.nodeWithAntiquot "simpPre" `Lean.Parser.Tactic.simpPre (Lean.ParserDescr.symbol "↓")
Instances For
Use this rewrite rule after entering the subterms
Equations
- Lean.Parser.Tactic.simpPost = Lean.ParserDescr.nodeWithAntiquot "simpPost" `Lean.Parser.Tactic.simpPost (Lean.ParserDescr.symbol "↑")
Instances For
A simp lemma specification is:
- optional
↑or↓to specify use before or after entering the subterm - optional
←to use the lemma backward thmfor the theorem to rewrite with
Equations
- One or more equations did not get rendered due to their size.
Instances For
An erasure specification -thm says to remove thm from the simp set
Equations
- One or more equations did not get rendered due to their size.
Instances For
The simp lemma specification * means to rewrite with all hypotheses
Equations
- Lean.Parser.Tactic.simpStar = Lean.ParserDescr.nodeWithAntiquot "simpStar" `Lean.Parser.Tactic.simpStar (Lean.ParserDescr.symbol "*")
Instances For
The simp tactic uses lemmas and hypotheses to simplify the main goal target or
non-dependent hypotheses. It has many variants:
simpsimplifies the main goal target using lemmas tagged with the attribute[simp].simp [h₁, h₂, ..., hₙ]simplifies the main goal target using the lemmas tagged with the attribute[simp]and the givenhᵢ's, where thehᵢ's are expressions.-- If an
hᵢis a defined constantf, thenfis unfolded. Iffhas equational lemmas associated with it (and is not a projection or areducibledefinition), these are used to rewrite withf. simp [*]simplifies the main goal target using the lemmas tagged with the attribute[simp]and all hypotheses.simp only [h₁, h₂, ..., hₙ]is likesimp [h₁, h₂, ..., hₙ]but does not use[simp]lemmas.simp [-id₁, ..., -idₙ]simplifies the main goal target using the lemmas tagged with the attribute[simp], but removes the ones namedidᵢ.simp at h₁ h₂ ... hₙsimplifies the hypothesesh₁ : T₁...hₙ : Tₙ. If the target or another hypothesis depends onhᵢ, a new simplified hypothesishᵢis introduced, but the old one remains in the local context.simp at *simplifies all the hypotheses and the target.simp [*] at *simplifies target and all (propositional) hypotheses using the other hypotheses.
Equations
- One or more equations did not get rendered due to their size.
Instances For
simp_all is a stronger version of simp [*] at * where the hypotheses and target
are simplified multiple times until no simplification is applicable.
Only non-dependent propositional hypotheses are considered.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A simpArg is either a *, -lemma or a simp lemma specification
(which includes the ↑ ↓ ← specifications for pre, post, reverse rewriting).
Equations
Instances For
The common arguments of simp? and simp?!.
Equations
- One or more equations did not get rendered due to their size.
Instances For
simp? takes the same arguments as simp, but reports an equivalent call to simp only
that would be sufficient to close the goal. This is useful for reducing the size of the simp
set in a local invocation to speed up processing.
example (x : Nat) : (if True then x + 2 else 3) = x + 2 := by
simp? -- prints "Try this: simp only [ite_true]"
This command can also be used in simp_all and dsimp.
Equations
- One or more equations did not get rendered due to their size.
Instances For
simp? takes the same arguments as simp, but reports an equivalent call to simp only
that would be sufficient to close the goal. This is useful for reducing the size of the simp
set in a local invocation to speed up processing.
example (x : Nat) : (if True then x + 2 else 3) = x + 2 := by
simp? -- prints "Try this: simp only [ite_true]"
This command can also be used in simp_all and dsimp.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The common arguments of simp_all? and simp_all?!.
Equations
- One or more equations did not get rendered due to their size.
Instances For
simp? takes the same arguments as simp, but reports an equivalent call to simp only
that would be sufficient to close the goal. This is useful for reducing the size of the simp
set in a local invocation to speed up processing.
example (x : Nat) : (if True then x + 2 else 3) = x + 2 := by
simp? -- prints "Try this: simp only [ite_true]"
This command can also be used in simp_all and dsimp.
Equations
- One or more equations did not get rendered due to their size.
Instances For
simp? takes the same arguments as simp, but reports an equivalent call to simp only
that would be sufficient to close the goal. This is useful for reducing the size of the simp
set in a local invocation to speed up processing.
example (x : Nat) : (if True then x + 2 else 3) = x + 2 := by
simp? -- prints "Try this: simp only [ite_true]"
This command can also be used in simp_all and dsimp.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The common arguments of dsimp? and dsimp?!.
Equations
- One or more equations did not get rendered due to their size.
Instances For
simp? takes the same arguments as simp, but reports an equivalent call to simp only
that would be sufficient to close the goal. This is useful for reducing the size of the simp
set in a local invocation to speed up processing.
example (x : Nat) : (if True then x + 2 else 3) = x + 2 := by
simp? -- prints "Try this: simp only [ite_true]"
This command can also be used in simp_all and dsimp.
Equations
- One or more equations did not get rendered due to their size.
Instances For
simp? takes the same arguments as simp, but reports an equivalent call to simp only
that would be sufficient to close the goal. This is useful for reducing the size of the simp
set in a local invocation to speed up processing.
example (x : Nat) : (if True then x + 2 else 3) = x + 2 := by
simp? -- prints "Try this: simp only [ite_true]"
This command can also be used in simp_all and dsimp.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The arguments to the simpa family tactics.
Equations
- One or more equations did not get rendered due to their size.
Instances For
This is a "finishing" tactic modification of simp. It has two forms.
simpa [rules, ⋯] using ewill simplify the goal and the type ofeusingrules, then try to close the goal usinge.
Simplifying the type of e makes it more likely to match the goal
(which has also been simplified). This construction also tends to be
more robust under changes to the simp lemma set.
simpa [rules, ⋯]will simplify the goal and the type of a hypothesisthisif present in the context, then try to close the goal using theassumptiontactic.
Equations
- One or more equations did not get rendered due to their size.
Instances For
This is a "finishing" tactic modification of simp. It has two forms.
simpa [rules, ⋯] using ewill simplify the goal and the type ofeusingrules, then try to close the goal usinge.
Simplifying the type of e makes it more likely to match the goal
(which has also been simplified). This construction also tends to be
more robust under changes to the simp lemma set.
simpa [rules, ⋯]will simplify the goal and the type of a hypothesisthisif present in the context, then try to close the goal using theassumptiontactic.
Equations
- One or more equations did not get rendered due to their size.
Instances For
This is a "finishing" tactic modification of simp. It has two forms.
simpa [rules, ⋯] using ewill simplify the goal and the type ofeusingrules, then try to close the goal usinge.
Simplifying the type of e makes it more likely to match the goal
(which has also been simplified). This construction also tends to be
more robust under changes to the simp lemma set.
simpa [rules, ⋯]will simplify the goal and the type of a hypothesisthisif present in the context, then try to close the goal using theassumptiontactic.
Equations
- One or more equations did not get rendered due to their size.
Instances For
This is a "finishing" tactic modification of simp. It has two forms.
simpa [rules, ⋯] using ewill simplify the goal and the type ofeusingrules, then try to close the goal usinge.
Simplifying the type of e makes it more likely to match the goal
(which has also been simplified). This construction also tends to be
more robust under changes to the simp lemma set.
simpa [rules, ⋯]will simplify the goal and the type of a hypothesisthisif present in the context, then try to close the goal using theassumptiontactic.
Equations
- One or more equations did not get rendered due to their size.
Instances For
delta id1 id2 ... delta-expands the definitions id1, id2, ....
This is a low-level tactic, it will expose how recursive definitions have been
compiled by Lean.
Equations
- One or more equations did not get rendered due to their size.
Instances For
unfold idunfolds all occurrences of definitionidin the target.unfold id1 id2 ...is equivalent tounfold id1; unfold id2; ....unfold id at hunfolds at the hypothesish.
Definitions can be either global or local definitions.
For non-recursive global definitions, this tactic is identical to delta.
For recursive global definitions, it uses the "unfolding lemma" id.eq_def,
which is generated for each recursive definition, to unfold according to the recursive definition given by the user.
Only one level of unfolding is performed, in contrast to simp only [id], which unfolds definition id recursively.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Auxiliary macro for lifting have/suffices/let/...
It makes sure the "continuation" ?_ is the main goal after refining.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The have tactic is for adding opaque definitions and hypotheses to the local context of the main goal.
The definitions forget their associated value and cannot be unfolded, unlike definitions added by the let tactic.
have h : t := eadds the hypothesish : tifeis a term of typet.have h := euses the type ofefort.have : t := eandhave := eusethisfor the name of the hypothesis.have pat := efor a patternpatis equivalent tomatch e with | pat => _, where_stands for the tactics that follow this one. It is convenient for types that have only one applicable constructor. For example, givenh : p ∧ q ∧ r,have ⟨h₁, h₂, h₃⟩ := hproduces the hypothesesh₁ : p,h₂ : q, andh₃ : r.- The syntax
have (eq := h) pat := eis equivalent tomatch h : e with | pat => _, which adds the equationh : e = patto the local context.
The tactic supports all the same syntax variants and options as the have term.
Properties and relations #
- It is not possible to unfold a variable introduced using
have, since the definition's value is forgotten. Thelettactic introduces definitions that can be unfolded. - The
have h : t := eis like doinglet h : t := e; clear_value h. - The
havetactic is preferred for propositions, andletis preferred for non-propositions. - Sometimes
haveis used for non-propositions to ensure that the variable is never unfolded, which may be important for performance reasons. Consider using the equivalentlet +nondepto indicate the intent.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Given a main goal ctx ⊢ t, suffices h : t' from e replaces the main goal with ctx ⊢ t',
e must have type t in the context ctx, h : t'.
The variant suffices h : t' by tac is a shorthand for suffices h : t' from by tac.
If h : is omitted, the name this is used.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The let tactic is for adding definitions to the local context of the main goal.
The definition can be unfolded, unlike definitions introduced by have.
let x : t := eadds the definitionx : t := eifeis a term of typet.let x := euses the type ofefort.let : t := eandlet := eusethisfor the name of the hypothesis.let pat := efor a patternpatis equivalent tomatch e with | pat => _, where_stands for the tactics that follow this one. It is convenient for types that let only one applicable constructor. For example, givenp : α × β × γ,let ⟨x, y, z⟩ := pproduces the local variablesx : α,y : β, andz : γ.- The syntax
let (eq := h) pat := eis equivalent tomatch h : e with | pat => _, which adds the equationh : e = patto the local context.
The tactic supports all the same syntax variants and options as the let term.
Properties and relations #
- Unlike
have, it is possible to unfold definitions introduced usinglet, using tactics such assimp,dsimp,unfold, andsubst. - The
clear_valuetactic turns aletdefinition into ahavedefinition after the fact. The tactic might fail if the local context depends on the value of the variable. - The
lettactic is preferred for data (non-propositions). - Sometimes
haveis used for non-propositions to ensure that the variable is never unfolded, which may be important for performance reasons.
Equations
- One or more equations did not get rendered due to their size.
Instances For
let rec f : t := e adds a recursive definition f to the current goal.
The syntax is the same as term-mode let rec.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Similar to refine_lift, but using refine'
Equations
- One or more equations did not get rendered due to their size.
Instances For
Similar to have, but using refine'
Equations
- One or more equations did not get rendered due to their size.
Instances For
Similar to let, but using refine'
Equations
- One or more equations did not get rendered due to their size.
Instances For
The left hand side of an induction arm, | foo a b c or | @foo a b c
where foo is a constructor of the inductive type and a b c are the arguments
to the constructor.
Equations
- One or more equations did not get rendered due to their size.
Instances For
In induction alternative, which can have 1 or more cases on the left
and _, ?_, or a tactic sequence after the =>.
Equations
- One or more equations did not get rendered due to their size.
Instances For
After with, there is an optional tactic that runs on all branches, and
then a list of alternatives.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A target for the induction or cases tactic, of the form e or h : e.
The h : e syntax introduces a hypotheses of the form h : e = _ in each goal,
with _ replaced by the corresponding value of the target.
It is useful when e is not a free variable.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Assuming x is a variable in the local context with an inductive type,
induction x applies induction on x to the main goal,
producing one goal for each constructor of the inductive type,
in which the target is replaced by a general instance of that constructor
and an inductive hypothesis is added for each recursive argument to the constructor.
If the type of an element in the local context depends on x,
that element is reverted and reintroduced afterward,
so that the inductive hypothesis incorporates that hypothesis as well.
For example, given n : Nat and a goal with a hypothesis h : P n and target Q n,
induction n produces one goal with hypothesis h : P 0 and target Q 0,
and one goal with hypotheses h : P (Nat.succ a) and ih₁ : P a → Q a and target Q (Nat.succ a).
Here the names a and ih₁ are chosen automatically and are not accessible.
You can use with to provide the variables names for each constructor.
induction e, whereeis an expression instead of a variable, generalizesein the goal, and then performs induction on the resulting variable.induction e using rallows the user to specify the principle of induction that should be used. Herershould be a term whose result type must be of the formC t, whereCis a bound variable andtis a (possibly empty) sequence of bound variablesinduction e generalizing z₁ ... zₙ, wherez₁ ... zₙare variables in the local context, generalizes overz₁ ... zₙbefore applying the induction but then introduces them in each goal. In other words, the net effect is that each inductive hypothesis is generalized.- Given
x : Nat,induction x with | zero => tac₁ | succ x' ih => tac₂uses tactictac₁for thezerocase, andtac₂for thesucccase.
Equations
- One or more equations did not get rendered due to their size.
Instances For
A generalize argument, of the form term = x or h : term = x.
Equations
- One or more equations did not get rendered due to their size.
Instances For
generalize ([h :] e = x),+replaces all occurrenceses in the main goal with a fresh hypothesisxs. Ifhis given,h : e = xis introduced as well.generalize e = x at h₁ ... hₙalso generalizes occurrences ofeinsideh₁, ...,hₙ.generalize e = x at *will generalize occurrences ofeeverywhere.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Assuming x is a variable in the local context with an inductive type,
cases x splits the main goal, producing one goal for each constructor of the
inductive type, in which the target is replaced by a general instance of that constructor.
If the type of an element in the local context depends on x,
that element is reverted and reintroduced afterward,
so that the case split affects that hypothesis as well.
cases detects unreachable cases and closes them automatically.
For example, given n : Nat and a goal with a hypothesis h : P n and target Q n,
cases n produces one goal with hypothesis h : P 0 and target Q 0,
and one goal with hypothesis h : P (Nat.succ a) and target Q (Nat.succ a).
Here the name a is chosen automatically and is not accessible.
You can use with to provide the variables names for each constructor.
cases e, whereeis an expression instead of a variable, generalizesein the goal, and then cases on the resulting variable.- Given
as : List α,cases as with | nil => tac₁ | cons a as' => tac₂, uses tactictac₁for thenilcase, andtac₂for theconscase, andaandas'are used as names for the new variables introduced. cases h : e, whereeis a variable or an expression, performs cases oneas above, but also adds a hypothesish : e = ...to each hypothesis, where...is the constructor instance for that particular case.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The fun_induction tactic is a convenience wrapper around the induction tactic to use the the
functional induction principle.
The tactic invocation
fun_induction f x₁ ... xₙ y₁ ... yₘ
where f is a function defined by non-mutual structural or well-founded recursion, is equivalent to
induction y₁, ... yₘ using f.induct_unfolding x₁ ... xₙ
where the arguments of f are used as arguments to f.induct_unfolding or targets of the
induction, as appropriate.
The form
fun_induction f
(with no arguments to f) searches the goal for a unique eligible application of f, and uses
these arguments. An application of f is eligible if it is saturated and the arguments that will
become targets are free variables.
The forms fun_induction f x y generalizing z₁ ... zₙ and
fun_induction f x y with | case1 => tac₁ | case2 x' ih => tac₂ work like with induction.
Under set_option tactic.fun_induction.unfolding true (the default), fun_induction uses the
f.induct_unfolding induction principle, which will try to automatically unfold the call to f in
the goal. With set_option tactic.fun_induction.unfolding false, it uses f.induct instead.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The fun_cases tactic is a convenience wrapper of the cases tactic when using a functional
cases principle.
The tactic invocation
fun_cases f x ... y ...`
is equivalent to
cases y, ... using f.fun_cases_unfolding x ...
where the arguments of f are used as arguments to f.fun_cases_unfolding or targets of the case
analysis, as appropriate.
The form
fun_cases f
(with no arguments to f) searches the goal for a unique eligible application of f, and uses
these arguments. An application of f is eligible if it is saturated and the arguments that will
become targets are free variables.
The form fun_cases f x y with | case1 => tac₁ | case2 x' ih => tac₂ works like with cases.
Under set_option tactic.fun_induction.unfolding true (the default), fun_induction uses the
f.fun_cases_unfolding theorem, which will try to automatically unfold the call to f in
the goal. With set_option tactic.fun_induction.unfolding false, it uses f.fun_cases instead.
Equations
- One or more equations did not get rendered due to their size.
Instances For
rename_i x_1 ... x_n renames the last n inaccessible names using the given names.
Equations
- One or more equations did not get rendered due to their size.
Instances For
repeat tac repeatedly applies tac so long as it succeeds.
The tactic tac may be a tactic sequence, and if tac fails at any point in its execution,
repeat will revert any partial changes that tac made to the tactic state.
The tactic tac should eventually fail, otherwise repeat tac will run indefinitely.
See also:
try tacis likerepeat tacbut will applytacat most once.repeat' tacrecursively appliestacto each goal.first | tac1 | tac2implements the backtracking used byrepeat
Equations
- One or more equations did not get rendered due to their size.
Instances For
repeat' tac recursively applies tac on all of the goals so long as it succeeds.
That is to say, if tac produces multiple subgoals, then repeat' tac is applied to each of them.
See also:
repeat tacsimply repeatedly appliestac.repeat1' tacisrepeat' tacbut requires thattacsucceed for some goal at least once.
Equations
- One or more equations did not get rendered due to their size.
Instances For
repeat1' tac recursively applies to tac on all of the goals so long as it succeeds,
but repeat1' tac fails if tac succeeds on none of the initial goals.
See also:
repeat tacsimply appliestacrepeatedly.repeat' tacis likerepeat1' tacbut it does not require thattacsucceed at least once.
Equations
- One or more equations did not get rendered due to their size.
Instances For
trivial tries different simple tactics (e.g., rfl, contradiction, ...)
to close the current goal.
You can use the command macro_rules to extend the set of tactics used. Example:
macro_rules | `(tactic| trivial) => `(tactic| simp)
Equations
- Lean.Parser.Tactic.tacticTrivial = Lean.ParserDescr.node `Lean.Parser.Tactic.tacticTrivial 1024 (Lean.ParserDescr.nonReservedSymbol "trivial" false)
Instances For
classical tacs runs tacs in a scope where Classical.propDecidable is a low priority
local instance.
Note that classical is a scoping tactic: it adds the instance only within the
scope of the tactic.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The split tactic is useful for breaking nested if-then-else and match expressions into separate cases.
For a match expression with n cases, the split tactic generates at most n subgoals.
For example, given n : Nat, and a target if n = 0 then Q else R, split will generate
one goal with hypothesis n = 0 and target Q, and a second goal with hypothesis
¬n = 0 and target R. Note that the introduced hypothesis is unnamed, and is commonly
renamed using the case or next tactics.
Equations
- One or more equations did not get rendered due to their size.
Instances For
stop is a helper tactic for "discarding" the rest of a proof:
it is defined as repeat sorry.
It is useful when working on the middle of a complex proofs,
and less messy than commenting the remainder of the proof.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The tactic specialize h a₁ ... aₙ works on local hypothesis h.
The premises of this hypothesis, either universal quantifications or
non-dependent implications, are instantiated by concrete terms coming
from arguments a₁ ... aₙ.
The tactic adds a new hypothesis with the same name h := h a₁ ... aₙ
and tries to clear the previous one.
Equations
- One or more equations did not get rendered due to their size.
Instances For
unhygienic tacs runs tacs with name hygiene disabled.
This means that tactics that would normally create inaccessible names will instead
make regular variables. Warning: Tactics may change their variable naming
strategies at any time, so code that depends on autogenerated names is brittle.
Users should try not to use unhygienic if possible.
example : ∀ x : Nat, x = x := by unhygienic
intro -- x would normally be intro'd as inaccessible
exact Eq.refl x -- refer to x
Equations
- One or more equations did not get rendered due to their size.
Instances For
The tactic sleep ms sleeps for ms milliseconds and does nothing.
It is used for debugging purposes only.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Apply congruence (recursively) to goals of the form ⊢ f as = f bs and ⊢ f as ≍ f bs.
The optional parameter is the depth of the recursive applications.
This is useful when congr is too aggressive in breaking down the goal.
For example, given ⊢ f (g (x + y)) = f (g (y + x)),
congr produces the goals ⊢ x = y and ⊢ y = x,
while congr 2 produces the intended ⊢ x + y = y + x.
Equations
- One or more equations did not get rendered due to their size.
Instances For
In tactic mode, if h : t then tac1 else tac2 can be used as alternative syntax for:
by_cases h : t
· tac1
· tac2
It performs case distinction on h : t or h : ¬t and tac1 and tac2 are the subproofs.
You can use ?_ or _ for either subproof to delay the goal to after the tactic, but
if a tactic sequence is provided for tac1 or tac2 then it will require the goal to be closed
by the end of the block.
Equations
- One or more equations did not get rendered due to their size.
Instances For
In tactic mode, if t then tac1 else tac2 is alternative syntax for:
by_cases t
· tac1
· tac2
It performs case distinction on h† : t or h† : ¬t, where h† is an anonymous
hypothesis, and tac1 and tac2 are the subproofs. (It doesn't actually use
nondependent if, since this wouldn't add anything to the context and hence would be
useless for proving theorems. To actually insert an ite application use
refine if t then ?_ else ?_.)
Equations
- One or more equations did not get rendered due to their size.
Instances For
The tactic nofun is shorthand for exact nofun: it introduces the assumptions, then performs an
empty pattern match, closing the goal if the introduced pattern is impossible.
Equations
- Lean.Parser.Tactic.tacticNofun = Lean.ParserDescr.node `Lean.Parser.Tactic.tacticNofun 1024 (Lean.ParserDescr.nonReservedSymbol "nofun" false)
Instances For
The tactic nomatch h is shorthand for exact nomatch h.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Acts like have, but removes a hypothesis with the same name as
this one if possible. For example, if the state is:
f : α → β
h : α
⊢ goal
Then after replace h := f h the state will be:
f : α → β
h : β
⊢ goal
whereas have h := f h would result in:
f : α → β
h† : α
h : β
⊢ goal
This can be used to simulate the specialize and apply at tactics of Coq.
Equations
- One or more equations did not get rendered due to their size.
Instances For
and_intros applies And.intro until it does not make progress.
Equations
- Lean.Parser.Tactic.tacticAnd_intros = Lean.ParserDescr.node `Lean.Parser.Tactic.tacticAnd_intros 1024 (Lean.ParserDescr.nonReservedSymbol "and_intros" false)
Instances For
subst_eq repeatedly substitutes according to the equality proof hypotheses in the context,
replacing the left side of the equality with the right, until no more progress can be made.
Equations
- Lean.Parser.Tactic.substEqs = Lean.ParserDescr.node `Lean.Parser.Tactic.substEqs 1024 (Lean.ParserDescr.nonReservedSymbol "subst_eqs" false)
Instances For
The run_tac doSeq tactic executes code in TacticM Unit.
Equations
- One or more equations did not get rendered due to their size.
Instances For
haveI behaves like have, but inlines the value instead of producing a have term.
Equations
- One or more equations did not get rendered due to their size.
Instances For
letI behaves like let, but inlines the value instead of producing a let term.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Configuration for the decide tactic family.
- kernel : Bool
If true (default: false), then use only kernel reduction when reducing the
Decidableinstance. This is more efficient, since the default mode reduces twice (once in the elaborator and again in the kernel), however kernel reduction ignores transparency settings. - native : Bool
If true (default: false), then uses the native code compiler to evaluate the
Decidableinstance, admitting the result via the axiomLean.ofReduceBool. This can be significantly more efficient, but it is at the cost of increasing the trusted code base, namely the Lean compiler and all definitions with an@[implemented_by]attribute. The instance is only evaluated once. Thenative_decidetactic is a synonym fordecide +native. - zetaReduce : Bool
If true (default: true), then when preprocessing the goal, do zeta reduction to attempt to eliminate free variables.
- revert : Bool
If true (default: false), then when preprocessing, removes irrelevant variables and reverts the local context. A variable is relevant if it appears in the target, if it appears in a relevant variable, or if it is a proposition that refers to a relevant variable.
Instances For
decide attempts to prove the main goal (with target type p) by synthesizing an instance of Decidable p
and then reducing that instance to evaluate the truth value of p.
If it reduces to isTrue h, then h is a proof of p that closes the goal.
The target is not allowed to contain local variables or metavariables.
If there are local variables, you can first try using the revert tactic with these local variables to move them into the target,
or you can use the +revert option, described below.
Options:
decide +revertbegins by reverting local variables that the target depends on, after cleaning up the local context of irrelevant variables. A variable is relevant if it appears in the target, if it appears in a relevant variable, or if it is a proposition that refers to a relevant variable.decide +kerneluses kernel for reduction instead of the elaborator. It has two key properties: (1) since it uses the kernel, it ignores transparency and can unfold everything, and (2) it reduces theDecidableinstance only once instead of twice.decide +nativeuses the native code compiler (#eval) to evaluate theDecidableinstance, admitting the result via theLean.ofReduceBoolaxiom. This can be significantly more efficient than using reduction, but it is at the cost of increasing the size of the trusted code base. Namely, it depends on the correctness of the Lean compiler and all definitions with an@[implemented_by]attribute. Like with+kernel, theDecidableinstance is evaluated only once.
Limitation: In the default mode or +kernel mode, since decide uses reduction to evaluate the term,
Decidable instances defined by well-founded recursion might not work because evaluating them requires reducing proofs.
Reduction can also get stuck on Decidable instances with Eq.rec terms.
These can appear in instances defined using tactics (such as rw and simp).
To avoid this, create such instances using definitions such as decidable_of_iff instead.
Examples #
Proving inequalities:
example : 2 + 2 ≠ 5 := by decide
Trying to prove a false proposition:
example : 1 ≠ 1 := by decide
/-
tactic 'decide' proved that the proposition
1 ≠ 1
is false
-/
Trying to prove a proposition whose Decidable instance fails to reduce
opaque unknownProp : Prop
open scoped Classical in
example : unknownProp := by decide
/-
tactic 'decide' failed for proposition
unknownProp
since its 'Decidable' instance reduced to
Classical.choice ⋯
rather than to the 'isTrue' constructor.
-/
Properties and relations #
For equality goals for types with decidable equality, usually rfl can be used in place of decide.
example : 1 + 1 = 2 := by decide
example : 1 + 1 = 2 := by rfl
Equations
- One or more equations did not get rendered due to their size.
Instances For
native_decide is a synonym for decide +native.
It will attempt to prove a goal of type p by synthesizing an instance
of Decidable p and then evaluating it to isTrue ... Unlike decide, this
uses #eval to evaluate the decidability instance.
This should be used with care because it adds the entire lean compiler to the trusted
part, and the axiom Lean.ofReduceBool will show up in #print axioms for theorems using
this method or anything that transitively depends on them. Nevertheless, because it is
compiled, this can be significantly more efficient than using decide, and for very
large computations this is one way to run external programs and trust the result.
example : (List.range 1000).length = 1000 := by native_decide
Equations
- One or more equations did not get rendered due to their size.
Instances For
The omega tactic, for resolving integer and natural linear arithmetic problems.
It is not yet a full decision procedure (no "dark" or "grey" shadows), but should be effective on many problems.
We handle hypotheses of the form x = y, x < y, x ≤ y, and k ∣ x for x y in Nat or Int
(and k a literal), along with negations of these statements.
We decompose the sides of the inequalities as linear combinations of atoms.
If we encounter x / k or x % k for literal integers k we introduce new auxiliary variables
and the relevant inequalities.
On the first pass, we do not perform case splits on natural subtraction.
If omega fails, we recursively perform a case split on
a natural subtraction appearing in a hypothesis, and try again.
The options
omega +splitDisjunctions +splitNatSub +splitNatAbs +splitMinMax
can be used to:
splitDisjunctions: split any disjunctions found in the context, if the problem is not otherwise solvable.splitNatSub: for each appearance of((a - b : Nat) : Int), split ona ≤ bif necessary.splitNatAbs: for each appearance ofInt.natAbs a, split on0 ≤ aif necessary.splitMinMax: for each occurrence ofmin a b, split onmin a b = a ∨ min a b = bCurrently, all of these are on by default.
Equations
- One or more equations did not get rendered due to their size.
Instances For
bv_omega is omega with an additional preprocessor that turns statements about BitVec into statements about Nat.
Currently the preprocessor is implemented as try simp only [bitvec_to_nat] at *.
bitvec_to_nat is a @[simp] attribute that you can (cautiously) add to more theorems.
Equations
- Lean.Parser.Tactic.tacticBv_omega = Lean.ParserDescr.node `Lean.Parser.Tactic.tacticBv_omega 1024 (Lean.ParserDescr.nonReservedSymbol "bv_omega" false)
Instances For
Implementation of ac_nf (the full ac_nf calls trivial afterwards).
Equations
- One or more equations did not get rendered due to their size.
Instances For
assumption_mod_cast is a variant of assumption that solves the goal
using a hypothesis. Unlike assumption, it first pre-processes the goal and
each hypothesis to move casts as far outwards as possible, so it can be used
in more situations.
Concretely, it runs norm_cast on the goal. For each local hypothesis h, it also
normalizes h with norm_cast and tries to use that to close the goal.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The norm_cast family of tactics is used to normalize certain coercions (casts) in expressions.
The tactic is basically a version of simp with a specific set of lemmas to move casts
upwards in the expression.
Therefore even in situations where non-terminal simp calls are discouraged (because of fragility),
norm_cast is considered to be safe.
It also has special handling of numerals.
For instance, given an assumption
a b : ℤ
h : ↑a + ↑b < (10 : ℚ)
writing norm_cast at h will turn h into
h : a + b < 10
There are also variants of basic tactics that use norm_cast to normalize expressions during
their operation, to make them more flexible about the expressions they accept
(we say that it is a tactic modulo the effects of norm_cast):
exact_mod_castforexactandapply_mod_castforapply. Writingexact_mod_cast handapply_mod_cast hwill normalize casts in the goal andhbefore usingexact horapply h.rw_mod_castforrw. It appliesnorm_castbetween rewrites.assumption_mod_castforassumption. This is effectivelynorm_cast at *; assumption, but more efficient. It normalizes casts in the goal and, for every hypothesishin the context, it will try to normalize casts inhand useexact h.
See also push_cast, which moves casts inwards rather than lifting them outwards.
Equations
- One or more equations did not get rendered due to their size.
Instances For
push_cast rewrites the goal to move certain coercions (casts) inward, toward the leaf nodes.
This uses norm_cast lemmas in the forward direction.
For example, ↑(a + b) will be written to ↑a + ↑b.
push_castmoves casts inward in the goal.push_cast at hmoves casts inward in the hypothesish. It can be used with extra simp lemmas with, for example,push_cast [Int.add_zero].
Example:
example (a b : Nat)
(h1 : ((a + b : Nat) : Int) = 10)
(h2 : ((a + b + 0 : Nat) : Int) = 10) :
((a + b : Nat) : Int) = 10 := by
/-
h1 : ↑(a + b) = 10
h2 : ↑(a + b + 0) = 10
⊢ ↑(a + b) = 10
-/
push_cast
/- Now
⊢ ↑a + ↑b = 10
-/
push_cast at h1
push_cast [Int.add_zero] at h2
/- Now
h1 h2 : ↑a + ↑b = 10
-/
exact h1
See also norm_cast.
Equations
- One or more equations did not get rendered due to their size.
Instances For
norm_cast_add_elim foo registers foo as an elim-lemma in norm_cast.
Equations
- One or more equations did not get rendered due to their size.
Instances For
ac_nf normalizes equalities up to application of an associative and commutative operator.
ac_nfnormalizes all hypotheses and the goal target of the goal.ac_nf at lnormalizes at location(s)l, wherelis either*or a list of hypotheses in the local context. In the latter case, a turnstile⊢or|-can also be used, to signify the target of the goal.
instance : Std.Associative (α := Nat) (.+.) := ⟨Nat.add_assoc⟩
instance : Std.Commutative (α := Nat) (.+.) := ⟨Nat.add_comm⟩
example (a b c d : Nat) : a + b + c + d = d + (b + c) + a := by
ac_nf
-- goal: a + (b + (c + d)) = a + (b + (c + d))
Equations
- One or more equations did not get rendered due to their size.
Instances For
symmapplies to a goal whose target has the formt ~ uwhere~is a symmetric relation, that is, a relation which has a symmetry lemma tagged with the attribute [symm]. It replaces the target withu ~ t.symm at hwill rewrite a hypothesish : t ~ utoh : u ~ t.
Equations
- One or more equations did not get rendered due to their size.
Instances For
For every hypothesis h : a ~ b where a @[symm] lemma is available,
add a hypothesis h_symm : b ~ a.
Equations
- Lean.Parser.Tactic.symmSaturate = Lean.ParserDescr.node `Lean.Parser.Tactic.symmSaturate 1024 (Lean.ParserDescr.nonReservedSymbol "symm_saturate" false)
Instances For
Syntax for omitting a local hypothesis in solve_by_elim.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Syntax for including all local hypotheses in solve_by_elim.
Equations
- Lean.Parser.Tactic.SolveByElim.star = Lean.ParserDescr.nodeWithAntiquot "star" `Lean.Parser.Tactic.SolveByElim.star (Lean.ParserDescr.symbol "*")
Instances For
Syntax for adding or removing a term, or *, in solve_by_elim.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Syntax for adding and removing terms in solve_by_elim.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Syntax for using all lemmas labelled with an attribute in solve_by_elim.
Equations
- One or more equations did not get rendered due to their size.
Instances For
solve_by_elim calls apply on the main goal to find an assumption whose head matches
and then repeatedly calls apply on the generated subgoals until no subgoals remain,
performing at most maxDepth (defaults to 6) recursive steps.
solve_by_elim discharges the current goal or fails.
solve_by_elim performs backtracking if subgoals can not be solved.
By default, the assumptions passed to apply are the local context, rfl, trivial,
congrFun and congrArg.
The assumptions can be modified with similar syntax as for simp:
solve_by_elim [h₁, h₂, ..., hᵣ]also applies the given expressions.solve_by_elim only [h₁, h₂, ..., hᵣ]does not include the local context,rfl,trivial,congrFun, orcongrArgunless they are explicitly included.solve_by_elim [-h₁, ... -hₙ]removes the given local hypotheses.solve_by_elim using [a₁, ...]uses all lemmas which have been labelled with the attributesaᵢ(these attributes must be created usingregister_label_attr).
solve_by_elim* tries to solve all goals together, using backtracking if a solution for one goal
makes other goals impossible.
(Adding or removing local hypotheses may not be well-behaved when starting with multiple goals.)
Optional arguments passed via a configuration argument as solve_by_elim (config := { ... })
maxDepth: number of attempts at discharging generated subgoalssymm: adds all hypotheses derived bysymm(defaults totrue).exfalso: allow callingexfalsoand trying again ifsolve_by_elimfails (defaults totrue).transparency: change the transparency mode when callingapply. Defaults to.default, but it is often useful to change to.reducible, so semireducible definitions will not be unfolded when trying to apply a lemma.
See also the doc-comment for Lean.Meta.Tactic.Backtrack.BacktrackConfig for the options
proc, suspend, and discharge which allow further customization of solve_by_elim.
Both apply_assumption and apply_rules are implemented via these hooks.
Equations
- One or more equations did not get rendered due to their size.
Instances For
apply_assumption looks for an assumption of the form ... → ∀ _, ... → head
where head matches the current goal.
You can specify additional rules to apply using apply_assumption [...].
By default apply_assumption will also try rfl, trivial, congrFun, and congrArg.
If you don't want these, or don't want to use all hypotheses, use apply_assumption only [...].
You can use apply_assumption [-h] to omit a local hypothesis.
You can use apply_assumption using [a₁, ...] to use all lemmas which have been labelled
with the attributes aᵢ (these attributes must be created using register_label_attr).
apply_assumption will use consequences of local hypotheses obtained via symm.
If apply_assumption fails, it will call exfalso and try again.
Thus if there is an assumption of the form P → ¬ Q, the new tactic state
will have two goals, P and Q.
You can pass a further configuration via the syntax apply_rules (config := {...}) lemmas.
The options supported are the same as for solve_by_elim (and include all the options for apply).
Equations
- One or more equations did not get rendered due to their size.
Instances For
apply_rules [l₁, l₂, ...] tries to solve the main goal by iteratively
applying the list of lemmas [l₁, l₂, ...] or by applying a local hypothesis.
If apply generates new goals, apply_rules iteratively tries to solve those goals.
You can use apply_rules [-h] to omit a local hypothesis.
apply_rules will also use rfl, trivial, congrFun and congrArg.
These can be disabled, as can local hypotheses, by using apply_rules only [...].
You can use apply_rules using [a₁, ...] to use all lemmas which have been labelled
with the attributes aᵢ (these attributes must be created using register_label_attr).
You can pass a further configuration via the syntax apply_rules (config := {...}).
The options supported are the same as for solve_by_elim (and include all the options for apply).
apply_rules will try calling symm on hypotheses and exfalso on the goal as needed.
This can be disabled with apply_rules (config := {symm := false, exfalso := false}).
You can bound the iteration depth using the syntax apply_rules (config := {maxDepth := n}).
Unlike solve_by_elim, apply_rules does not perform backtracking, and greedily applies
a lemma from the list until it gets stuck.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Searches environment for definitions or theorems that can solve the goal using exact
with conditions resolved by solve_by_elim.
The optional using clause provides identifiers in the local context that must be
used by exact? when closing the goal. This is most useful if there are multiple
ways to resolve the goal, and one wants to guide which lemma is used.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Searches environment for definitions or theorems that can refine the goal using apply
with conditions resolved when possible with solve_by_elim.
The optional using clause provides identifiers in the local context that must be
used when closing the goal.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Syntax for excluding some names, e.g. [-my_lemma, -my_theorem].
Equations
- One or more equations did not get rendered due to their size.
Instances For
rw? tries to find a lemma which can rewrite the goal.
rw? should not be left in proofs; it is a search tool, like apply?.
Suggestions are printed as rw [h] or rw [← h].
You can use rw? [-my_lemma, -my_theorem] to prevent rw? using the named lemmas.
Equations
- One or more equations did not get rendered due to their size.
Instances For
show_term tac runs tac, then prints the generated term in the form
"exact X Y Z" or "refine X ?_ Z" (prefixed by expose_names if necessary)
if there are remaining subgoals.
(For some tactics, the printed term will not be human readable.)
Equations
- One or more equations did not get rendered due to their size.
Instances For
show_term e elaborates e, then prints the generated term.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The command by? will print a suggestion for replacing the proof block with a proof term
using show_term.
Equations
- Lean.Parser.Tactic.by? = Lean.ParserDescr.node `Lean.Parser.Tactic.by? 1022 (Lean.ParserDescr.binary `andthen (Lean.ParserDescr.symbol "by?") (Lean.ParserDescr.const `tacticSeq))
Instances For
expose_names renames all inaccessible variables with accessible names, making them available
for reference in generated tactics. However, this renaming introduces machine-generated names
that are not fully under user control. expose_names is primarily intended as a preamble for
auto-generated end-game tactic scripts. It is also useful as an alternative to
set_option tactic.hygienic false. If explicit control over renaming is needed in the
middle of a tactic script, consider using structured tactic scripts with
match .. with, induction .. with, or intro with explicit user-defined names,
as well as tactics such as next, case, and rename_i.
Equations
- Lean.Parser.Tactic.exposeNames = Lean.ParserDescr.node `Lean.Parser.Tactic.exposeNames 1024 (Lean.ParserDescr.nonReservedSymbol "expose_names" false)
Instances For
#suggest_premises will suggest premises for the current goal, using the currently registered premise selector.
The suggestions are printed in the order of their confidence, from highest to lowest.
Equations
- Lean.Parser.Tactic.suggestPremises = Lean.ParserDescr.node `Lean.Parser.Tactic.suggestPremises 1024 (Lean.ParserDescr.nonReservedSymbol "suggest_premises" false)
Instances For
Close fixed-width BitVec and Bool goals by obtaining a proof from an external SAT solver and
verifying it inside Lean. The solvable goals are currently limited to
- the Lean equivalent of
QF_BV - automatically splitting up
structures that contain information aboutBitVecorBool
example : ∀ (a b : BitVec 64), (a &&& b) + (a ^^^ b) = a ||| b := by
intros
bv_decide
If bv_decide encounters an unknown definition it will be treated like an unconstrained BitVec
variable. Sometimes this enables solving goals despite not understanding the definition because
the precise properties of the definition do not matter in the specific proof.
If bv_decide fails to close a goal it provides a counter-example, containing assignments for all
terms that were considered as variables.
In order to avoid calling a SAT solver every time, the proof can be cached with bv_decide?.
If solving your problem relies inherently on using associativity or commutativity, consider enabling
the bv.ac_nf option.
Note: bv_decide uses ofReduceBool and thus trusts the correctness of the code generator.
Note: include import Std.Tactic.BVDecide
Equations
- One or more equations did not get rendered due to their size.
Instances For
Suggest a proof script for a bv_decide tactic call. Useful for caching LRAT proofs.
Note: include import Std.Tactic.BVDecide
Equations
- One or more equations did not get rendered due to their size.
Instances For
Run the normalization procedure of bv_decide only. Sometimes this is enough to solve basic
BitVec goals already.
Note: include import Std.Tactic.BVDecide
Equations
- One or more equations did not get rendered due to their size.
Instances For
massumption is like assumption, but operating on a stateful Std.Do.SPred goal.
example (P Q : SPred σs) : Q ⊢ₛ P → Q := by
mintro _ _
massumption
Equations
- Lean.Parser.Tactic.massumptionMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.massumptionMacro 1024 (Lean.ParserDescr.nonReservedSymbol "massumption" false)
Instances For
mclear is like clear, but operating on a stateful Std.Do.SPred goal.
example (P Q : SPred σs) : P ⊢ₛ Q → Q := by
mintro HP
mintro HQ
mclear HP
mexact HQ
Equations
- Lean.Parser.Tactic.mclearMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mclearMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mclear" false)
Instances For
mconstructor is like constructor, but operating on a stateful Std.Do.SPred goal.
example (Q : SPred σs) : Q ⊢ₛ Q ∧ Q := by
mintro HQ
mconstructor <;> mexact HQ
Equations
- Lean.Parser.Tactic.mconstructorMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mconstructorMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mconstructor" false)
Instances For
mexact is like exact, but operating on a stateful Std.Do.SPred goal.
example (Q : SPred σs) : Q ⊢ₛ Q := by
mstart
mintro HQ
mexact HQ
Equations
- Lean.Parser.Tactic.mexactMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mexactMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mexact" false)
Instances For
mexfalso is like exfalso, but operating on a stateful Std.Do.SPred goal.
example (P : SPred σs) : ⌜False⌝ ⊢ₛ P := by
mintro HP
mexfalso
mexact HP
Equations
- Lean.Parser.Tactic.mexfalsoMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mexfalsoMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mexfalso" false)
Instances For
mexists is like exists, but operating on a stateful Std.Do.SPred goal.
example (ψ : Nat → SPred σs) : ψ 42 ⊢ₛ ∃ x, ψ x := by
mintro H
mexists 42
Equations
- Lean.Parser.Tactic.mexistsMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mexistsMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mexists" false)
Instances For
mframe infers which hypotheses from the stateful context can be moved into the pure context.
This is useful because pure hypotheses "survive" the next application of modus ponens
(Std.Do.SPred.mp) and transitivity (Std.Do.SPred.entails.trans).
It is used as part of the mspec tactic.
example (P Q : SPred σs) : ⊢ₛ ⌜p⌝ ∧ Q ∧ ⌜q⌝ ∧ ⌜r⌝ ∧ P ∧ ⌜s⌝ ∧ ⌜t⌝ → Q := by
mintro _
mframe
/- `h : p ∧ q ∧ r ∧ s ∧ t` in the pure context -/
mcases h with hP
mexact h
Equations
- Lean.Parser.Tactic.mframeMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mframeMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mframe" false)
Instances For
mhave is like have, but operating on a stateful Std.Do.SPred goal.
example (P Q : SPred σs) : P ⊢ₛ (P → Q) → Q := by
mintro HP HPQ
mhave HQ : Q := by mspecialize HPQ HP; mexact HPQ
mexact HQ
Equations
- Lean.Parser.Tactic.mhaveMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mhaveMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mhave" false)
Instances For
mreplace is like replace, but operating on a stateful Std.Do.SPred goal.
example (P Q : SPred σs) : P ⊢ₛ (P → Q) → Q := by
mintro HP HPQ
mreplace HPQ : Q := by mspecialize HPQ HP; mexact HPQ
mexact HPQ
Equations
- Lean.Parser.Tactic.mreplaceMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mreplaceMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mreplace" false)
Instances For
mleft is like left, but operating on a stateful Std.Do.SPred goal.
example (P Q : SPred σs) : P ⊢ₛ P ∨ Q := by
mintro HP
mleft
mexact HP
Equations
- Lean.Parser.Tactic.mleftMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mleftMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mleft" false)
Instances For
mright is like right, but operating on a stateful Std.Do.SPred goal.
example (P Q : SPred σs) : P ⊢ₛ Q ∨ P := by
mintro HP
mright
mexact HP
Equations
- Lean.Parser.Tactic.mrightMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mrightMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mright" false)
Instances For
mpure moves a pure hypothesis from the stateful context into the pure context.
example (Q : SPred σs) (ψ : φ → ⊢ₛ Q): ⌜φ⌝ ⊢ₛ Q := by
mintro Hφ
mpure Hφ
mexact (ψ Hφ)
Equations
- Lean.Parser.Tactic.mpureMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mpureMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mpure" false)
Instances For
mpure_intro operates on a stateful Std.Do.SPred goal of the form P ⊢ₛ ⌜φ⌝.
It leaves the stateful proof mode (thereby discarding P), leaving the regular goal φ.
theorem simple : ⊢ₛ (⌜True⌝ : SPred σs) := by
mpure_intro
exact True.intro
Equations
- Lean.Parser.Tactic.mpureIntroMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mpureIntroMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mpure_intro" false)
Instances For
mrevert is like revert, but operating on a stateful Std.Do.SPred goal.
example (P Q R : SPred σs) : P ∧ Q ∧ R ⊢ₛ P → R := by
mintro ⟨HP, HQ, HR⟩
mrevert HR
mrevert HP
mintro HP'
mintro HR'
mexact HR'
Equations
- Lean.Parser.Tactic.mrevertMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mrevertMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mrevert" false)
Instances For
mrename_i is like rename_i, but names inaccessible stateful hypotheses in a Std.Do.SPred goal.
Equations
- Lean.Parser.Tactic.mrenameIMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mrenameIMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mrename_i" false)
Instances For
mspecialize is like specialize, but operating on a stateful Std.Do.SPred goal.
It specializes a hypothesis from the stateful context with hypotheses from either the pure
or stateful context or pure terms.
example (P Q : SPred σs) : P ⊢ₛ (P → Q) → Q := by
mintro HP HPQ
mspecialize HPQ HP
mexact HPQ
example (y : Nat) (P Q : SPred σs) (Ψ : Nat → SPred σs) (hP : ⊢ₛ P) : ⊢ₛ Q → (∀ x, P → Q → Ψ x) → Ψ (y + 1) := by
mintro HQ HΨ
mspecialize HΨ (y + 1) hP HQ
mexact HΨ
Equations
- Lean.Parser.Tactic.mspecializeMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mspecializeMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mspecialize" false)
Instances For
mspecialize_pure is like mspecialize, but it specializes a hypothesis from the
pure context with hypotheses from either the pure or stateful context or pure terms.
example (y : Nat) (P Q : SPred σs) (Ψ : Nat → SPred σs) (hP : ⊢ₛ P) (hΨ : ∀ x, ⊢ₛ P → Q → Ψ x) : ⊢ₛ Q → Ψ (y + 1) := by
mintro HQ
mspecialize_pure (hΨ (y + 1)) hP HQ => HΨ
mexact HΨ
Equations
- Lean.Parser.Tactic.mspecializePureMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mspecializePureMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mspecialize_pure" false)
Instances For
Start the stateful proof mode of Std.Do.SPred.
This will transform a stateful goal of the form H ⊢ₛ T into ⊢ₛ H → T
upon which mintro can be used to re-introduce H and give it a name.
It is often more convenient to use mintro directly, which will
try mstart automatically if necessary.
Equations
- Lean.Parser.Tactic.mstartMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mstartMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mstart" false)
Instances For
Stops the stateful proof mode of Std.Do.SPred.
This will simply forget all the names given to stateful hypotheses and pretty-print
a bit differently.
Equations
- Lean.Parser.Tactic.mstopMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mstopMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mstop" false)
Instances For
Leaves the stateful proof mode of Std.Do.SPred, tries to eta-expand through all definitions
related to the logic of the Std.Do.SPred and gently simplifies the resulting pure Lean
proposition. This is often the right thing to do after mvcgen in order for automation to prove
the goal.
Equations
- Lean.Parser.Tactic.mleaveMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mleaveMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mleave" false)
Instances For
Like rcases, but operating on stateful Std.Do.SPred goals.
Example: Given a goal h : (P ∧ (Q ∨ R) ∧ (Q → R)) ⊢ₛ R,
mcases h with ⟨-, ⟨hq | hr⟩, hqr⟩ will yield two goals:
(hq : Q, hqr : Q → R) ⊢ₛ R and (hr : R) ⊢ₛ R.
That is, mcases h with pat has the following semantics, based on pat:
pat=□h'renameshtoh'in the stateful context, regardless of whetherhis purepat=⌜h'⌝introducesh' : φto the pure local context ifh : ⌜φ⌝(c.f.Lean.Elab.Tactic.Do.ProofMode.IsPure)pat=h'is likepat=⌜h'⌝ifhis pure (c.f.Lean.Elab.Tactic.Do.ProofMode.IsPure), otherwise it is likepat=□h'.pat=_renameshto an inaccessible namepat=-discardsh⟨pat₁, pat₂⟩matches on conjunctions and existential quantifiers and recurses viapat₁andpat₂.⟨pat₁ | pat₂⟩matches on disjunctions, matching the left alternative viapat₁and the right alternative viapat₂.
Equations
- Lean.Parser.Tactic.mcasesMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mcasesMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mcases" false)
Instances For
Like refine, but operating on stateful Std.Do.SPred goals.
example (P Q R : SPred σs) : (P ∧ Q ∧ R) ⊢ₛ P ∧ R := by
mintro ⟨HP, HQ, HR⟩
mrefine ⟨HP, HR⟩
example (ψ : Nat → SPred σs) : ψ 42 ⊢ₛ ∃ x, ψ x := by
mintro H
mrefine ⟨⌜42⌝, H⟩
Equations
- Lean.Parser.Tactic.mrefineMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mrefineMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mrefine" false)
Instances For
Like intro, but introducing stateful hypotheses into the stateful context of the Std.Do.SPred
proof mode.
That is, given a stateful goal (hᵢ : Hᵢ)* ⊢ₛ P → T, mintro h transforms
into (hᵢ : Hᵢ)*, (h : P) ⊢ₛ T.
Furthermore, mintro ∀s is like intro s, but preserves the stateful goal.
That is, mintro ∀s brings the topmost state variable s:σ in scope and transforms
(hᵢ : Hᵢ)* ⊢ₛ T (where the entailment is in Std.Do.SPred (σ::σs)) into
(hᵢ : Hᵢ s)* ⊢ₛ T s (where the entailment is in Std.Do.SPred σs).
Beyond that, mintro supports the full syntax of mcases patterns
(mintro pat = (mintro h; mcases h with pat), and can perform multiple
introductions in sequence.
Equations
- Lean.Parser.Tactic.mintroMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mintroMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mintro" false)
Instances For
mspec is an apply-like tactic that applies a Hoare triple specification to the target of the
stateful goal.
Given a stateful goal H ⊢ₛ wp⟦prog⟧ Q', mspec foo_spec will instantiate
foo_spec : ... → ⦃P⦄ foo ⦃Q⦄, match foo against prog and produce subgoals for
the verification conditions ?pre : H ⊢ₛ P and ?post : Q ⊢ₚ Q'.
- If
prog = x >>= f, thenmspec Specs.bindis tried first so thatfoois matched againstxinstead. Tacticmspec_no_binddoes not attempt to do this decomposition. - If
?preor?postfollow by.rfl, then they are discharged automatically. ?postis automatically simplified into constituent⊢ₛentailments on success and failure continuations.?preand?post.*goals introduce their stateful hypothesis under an inaccessible name. You can give it a name with themrename_itactic.- Any uninstantiated MVar arising from instantiation of
foo_specbecomes a new subgoal. - If the target of the stateful goal looks like
fun s => _thenmspecwill firstmintro ∀s. - If
Phas schematic variables that can be instantiated by doingmintro ∀s, for examplefoo_spec : ∀(n:Nat), ⦃fun s => ⌜n = s⌝⦄ foo ⦃Q⦄, thenmspecwill domintro ∀sfirst to instantiaten = s. - Right before applying the spec, the
mframetactic is used, which has the following effect: Any hypothesisHᵢin the goalh₁:H₁, h₂:H₂, ..., hₙ:Hₙ ⊢ₛ Tthat is pure (i.e., equivalent to some⌜φᵢ⌝) will be moved into the pure context ashᵢ:φᵢ.
Additionally, mspec can be used without arguments or with a term argument:
mspecwithout argument will try and look up a spec forxregistered with@[spec].mspec (foo_spec blah ?bleh)will elaborate its argument as a term with expected type⦃?P⦄ x ⦃?Q⦄and introduce?blehas a subgoal. This is useful to pass an invariant to e.g.,Specs.forIn_listand leave the inductive step as a hole.
Equations
- Lean.Parser.Tactic.mspecMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mspecMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mspec" false)
Instances For
mvcgen will break down a Hoare triple proof goal like ⦃P⦄ prog ⦃Q⦄ into verification conditions,
provided that all functions used in prog have specifications registered with @[spec].
Verification Conditions and specifications #
A verification condition is an entailment in the stateful logic of Std.Do.SPred
in which the original program prog no longer occurs.
Verification conditions are introduced by the mspec tactic; see the mspec tactic for what they
look like.
When there's no applicable mspec spec, mvcgen will try and rewrite an application
prog = f a b c with the simp set registered via @[spec].
Features #
When used like mvcgen +noLetElim [foo_spec, bar_def, instBEqFloat], mvcgen will additionally
- add a Hoare triple specification
foo_spec : ... → ⦃P⦄ foo ... ⦃Q⦄tospecset for a functionfoooccurring inprog, - unfold a definition
def bar_def ... := ...inprog, - unfold any method of the
instBEqFloat : BEq Floatinstance inprog. - it will no longer substitute away
let-expressions that occur at most once inP,Qorprog.
Config options #
+noLetElim is just one config option of many. Check out Lean.Elab.Tactic.Do.VCGen.Config for all
options. Of particular note is stepLimit = some 42, which is useful for bisecting bugs in
mvcgen and tracing its execution.
Extended syntax #
Often, mvcgen will be used like this:
mvcgen [...]
case inv1 => by exact I1
case inv2 => by exact I2
all_goals (mleave; try grind)
There is special syntax for this:
mvcgen [...] invariants
· I1
· I2
with grind
When I1 and I2 need to refer to inaccessibles (mvcgen will introduce a lot of them for program
variables), you can use case label syntax:
mvcgen [...] invariants
| inv1 _ acc _ => I1 acc
| _ => I2
with grind
This is more convenient than the equivalent · by rename_i _ acc _; exact I1 acc.
Invariant suggestions #
mvcgen will suggest invariants for you if you use the invariants? keyword.
mvcgen [...] invariants?
This is useful if you do not recall the exact syntax to construct invariants. Furthermore, it will suggest a concrete invariant encoding "this holds at the start of the loop and this must hold at the end of the loop" by looking at the corresponding VCs. Although the suggested invariant is a good starting point, it is too strong and requires users to interpolate it such that the inductive step can be proved. Example:
def mySum (l : List Nat) : Nat := Id.run do
let mut acc := 0
for x in l do
acc := acc + x
return acc
/--
info: Try this:
invariants
· ⇓⟨xs, letMuts⟩ => ⌜xs.prefix = [] ∧ letMuts = 0 ∨ xs.suffix = [] ∧ letMuts = l.sum⌝
-/
#guard_msgs (info) in
theorem mySum_suggest_invariant (l : List Nat) : mySum l = l.sum := by
generalize h : mySum l = r
apply Id.of_wp_run_eq h
mvcgen invariants?
all_goals admit
Equations
- Lean.Parser.Tactic.mvcgenMacro = Lean.ParserDescr.node `Lean.Parser.Tactic.mvcgenMacro 1024 (Lean.ParserDescr.nonReservedSymbol "mvcgen" false)
Instances For
Theorems tagged with the simp attribute are used by the simplifier
(i.e., the simp tactic, and its variants) to simplify expressions occurring in your goals.
We call theorems tagged with the simp attribute "simp theorems" or "simp lemmas".
Lean maintains a database/index containing all active simp theorems.
Here is an example of a simp theorem.
@[simp] theorem ne_eq (a b : α) : (a ≠ b) = Not (a = b) := rfl
This simp theorem instructs the simplifier to replace instances of the term
a ≠ b (e.g. x + 0 ≠ y) with Not (a = b) (e.g., Not (x + 0 = y)).
The simplifier applies simp theorems in one direction only:
if A = B is a simp theorem, then simp replaces As with Bs,
but it doesn't replace Bs with As. Hence a simp theorem should have the
property that its right-hand side is "simpler" than its left-hand side.
In particular, = and ↔ should not be viewed as symmetric operators in this situation.
The following would be a terrible simp theorem (if it were even allowed):
@[simp] lemma mul_right_inv_bad (a : G) : 1 = a * a⁻¹ := ...
Replacing 1 with a * a⁻¹ is not a sensible default direction to travel. Even worse would be a theorem that causes expressions to grow without bound, causing simp to loop forever.
By default the simplifier applies simp theorems to an expression e
after its sub-expressions have been simplified.
We say it performs a bottom-up simplification.
You can instruct the simplifier to apply a theorem before its sub-expressions
have been simplified by using the modifier ↓. Here is an example
@[simp↓] theorem not_and_eq (p q : Prop) : (¬ (p ∧ q)) = (¬p ∨ ¬q) :=
You can instruct the simplifier to rewrite the lemma from right-to-left:
attribute @[simp ←] and_assoc
When multiple simp theorems are applicable, the simplifier uses the one with highest priority. The equational theorems of functions are applied at very low priority (100 and below). If there are several with the same priority, it is uses the "most recent one". Example:
@[simp high] theorem cond_true (a b : α) : cond true a b = a := rfl
@[simp low+1] theorem or_true (p : Prop) : (p ∨ True) = True :=
propext <| Iff.intro (fun _ => trivial) (fun _ => Or.inr trivial)
@[simp 100] theorem ite_self {d : Decidable c} (a : α) : ite c a a = a := by
cases d <;> rfl
Equations
- One or more equations did not get rendered due to their size.
Instances For
Theorems tagged with the wf_preprocess attribute are used during the processing of functions defined
by well-founded recursion. They are applied to the function's body to add additional hypotheses,
such as replacing if c then _ else _ with if h : c then _ else _ or xs.map with
xs.attach.map. Also see wfParam.
Equations
- One or more equations did not get rendered due to their size.
Instances For
Theorems tagged with the method_specs_simp attribute are used by @[method_specs] to further
rewrite the theorem statement. This is primarily used to rewrite type class methods further to
the desired user-visible form, e.g. from Append.append to HAppend.hAppend, which has the familiar
notation associated.
The method_specs theorems are created on demand (using the realizable constant feature). Thus,
this simp set should behave the same in all modules. Do not add theorems to it except in the module
defining the thing you are rewriting.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The possible norm_cast kinds: elim, move, or squash.
Equations
- One or more equations did not get rendered due to their size.
Instances For
The norm_cast attribute should be given to lemmas that describe the
behaviour of a coercion with respect to an operator, a relation, or a particular
function.
It only concerns equality or iff lemmas involving ↑, ⇑ and ↥, describing the behavior of
the coercion functions.
It does not apply to the explicit functions that define the coercions.
Examples:
@[norm_cast] theorem coe_nat_inj' {m n : ℕ} : (↑m : ℤ) = ↑n ↔ m = n
@[norm_cast] theorem coe_int_denom (n : ℤ) : (n : ℚ).denom = 1
@[norm_cast] theorem cast_id : ∀ n : ℚ, ↑n = n
@[norm_cast] theorem coe_nat_add (m n : ℕ) : (↑(m + n) : ℤ) = ↑m + ↑n
@[norm_cast] theorem cast_coe_nat (n : ℕ) : ((n : ℤ) : α) = n
@[norm_cast] theorem cast_one : ((1 : ℚ) : α) = 1
Lemmas tagged with @[norm_cast] are classified into three categories: move, elim, and
squash. They are classified roughly as follows:
- elim lemma: LHS has 0 head coes and ≥ 1 internal coe
- move lemma: LHS has 1 head coe and 0 internal coes, RHS has 0 head coes and ≥ 1 internal coes
- squash lemma: LHS has ≥ 1 head coes and 0 internal coes, RHS has fewer head coes
norm_cast uses move and elim lemmas to factor coercions toward the root of an expression
and to cancel them from both sides of an equation or relation. It uses squash lemmas to clean
up the result.
It is typically not necessary to specify these categories, as norm_cast lemmas are
automatically classified by default. The automatic classification can be overridden by
giving an optional elim, move, or squash parameter to the attribute.
@[simp, norm_cast elim] lemma nat_cast_re (n : ℕ) : (n : ℂ).re = n := by
rw [← of_real_nat_cast, of_real_re]
Don't do this unless you understand what you are doing.
Equations
- One or more equations did not get rendered due to their size.
Instances For
‹t› resolves to an (arbitrary) hypothesis of type t.
It is useful for referring to hypotheses without accessible names.
t may contain holes that are solved by unification with the expected type;
in particular, ‹_› is a shortcut for by assumption.
Equations
- One or more equations did not get rendered due to their size.
Instances For
get_elem_tactic_extensible is an extensible tactic automatically called
by the notation arr[i] to prove any side conditions that arise when
constructing the term (e.g. the index is in bounds of the array).
The default behavior is to try simp +arith and omega
(for doing linear arithmetic in the index).
(Note that the core tactic get_elem_tactic has already tried
done and assumption before the extensible tactic is called.)
Equations
- tacticGet_elem_tactic_extensible = Lean.ParserDescr.node `tacticGet_elem_tactic_extensible 1024 (Lean.ParserDescr.nonReservedSymbol "get_elem_tactic_extensible" false)
Instances For
get_elem_tactic_trivial has been deprecated in favour of get_elem_tactic_extensible.
Equations
- tacticGet_elem_tactic_trivial = Lean.ParserDescr.node `tacticGet_elem_tactic_trivial 1024 (Lean.ParserDescr.nonReservedSymbol "get_elem_tactic_trivial" false)
Instances For
get_elem_tactic is the tactic automatically called by the notation arr[i]
to prove any side conditions that arise when constructing the term
(e.g. the index is in bounds of the array). It just delegates to
get_elem_tactic_extensible and gives a diagnostic error message otherwise;
users are encouraged to extend get_elem_tactic_extensible instead of this tactic.
Equations
- tacticGet_elem_tactic = Lean.ParserDescr.node `tacticGet_elem_tactic 1024 (Lean.ParserDescr.nonReservedSymbol "get_elem_tactic" false)
Instances For
Searches environment for definitions or theorems that can be substituted in
for exact?% to solve the goal.
Equations
- Lean.Parser.Syntax.exact? = Lean.ParserDescr.node `Lean.Parser.Syntax.exact? 1024 (Lean.ParserDescr.symbol "exact?%")