The push, push_neg and pull tactics #
The push tactic pushes a given constant inside expressions: it can be applied to goals as well
as local hypotheses and also works as a conv tactic. push_neg is a macro for push Not.
The pull tactic does the reverse: it pulls the given constant towards the head of the expression.
Common entry point to the implementation of push.
Equations
Instances For
Common entry point to the implementation of pull.
Equations
Instances For
Return true if stx is an underscore, i.e. _ or fun $_ => _/fun $_ ↦ _.
Equations
Instances For
resolvePushId? is a version of resolveId? that also supports notations like _ ∈ _,
∃ x, _ and ∑ x, _.
Equations
Instances For
Elaborator for the argument passed to push. It accepts a constant, or a function
Equations
Instances For
Elaborate the (disch := ...) syntax for a simp-like tactic.
Equations
Instances For
Run the push tactic.
Equations
Instances For
push c rewrites the goal by pushing the constant c deeper into an expression.
For instance, push _ ∈ _ rewrites x ∈ {y} ∪ zᶜ into x = y ∨ ¬ x ∈ z.
More precisely, the push tactic repeatedly rewrites an expression by applying lemmas
of the form c ... = ... (c ...) (where c can appear 0 or more times on the right hand side).
To extend the push tactic, you can tag a lemma of this form with the @[push] attribute.
To instead move a constant closer to the head of the expression, use the pull tactic.
push works as both a tactic and a conv tactic.
push _ ~ _pushes the (binary) operator~,push ~ _pushes the (unary) operator~.push c at l1 l2 ...rewrites at the given locations.push c at *rewrites at all hypotheses and the goal.push (disch := tac) cuses the tactictacto discharge any hypotheses for@[push]lemmas.
Examples:
push _ ∈ _rewritesx ∈ {y} ∪ zᶜintox = y ∨ ¬ x ∈ z.push (disch := positivity) Real.logrewriteslog (a * b ^ 2)intolog a + 2 * log b.push ¬ _is the same aspush_negorpush Not, and it rewrites¬ ∀ ε > 0, ∃ δ > 0, δ < εinto∃ ε > 0, ∀ δ > 0, ε ≤ δ.push fun _ ↦ _rewritesfun x => f x ^ 2 + 5intof ^ 2 + 5push ∀ _, _rewrites∀ a, p a ∧ q ainto(∀ a, p a) ∧ (∀ a, q a).
Equations
Instances For
push_neg rewrites the goal by pushing negations deeper into an expression.
For instance, the goal ¬ ∀ x, ∃ y, x ≤ y will be transformed by push_neg into
∃ x, ∀ y, y < x. Binder names are preserved (contrary to what would happen with simp
using the relevant lemmas). push_neg works as both a tactic and a conv tactic.
push_neg is a special case of the more general push tactic, namely push Not.
The push tactic can be extended using the @[push] attribute. push has special-casing
built in for push Not.
Tactics that introduce a negation usually have a version that automatically calls push_neg on
that negation. These include by_cases!, contrapose! and by_contra!.
push_neg at l1 l2 ...rewrites at the given locations.push_neg at *rewrites at each hypothesis and the goal.push_neg +distribrewrites¬ (p ∧ q)into¬ p ∨ ¬ q(by default, the tactic rewrites it intop → ¬ qinstead).
Example:
example (h : ¬ ∀ ε > 0, ∃ δ > 0, ∀ x, |x - x₀| ≤ δ → |f x - y₀| ≤ ε) :
∃ ε > 0, ∀ δ > 0, ∃ x, |x - x₀| ≤ δ ∧ ε < |f x - y₀| := by
push_neg at h
-- Now we have the hypothesis `h : ∃ ε > 0, ∀ δ > 0, ∃ x, |x - x₀| ≤ δ ∧ ε < |f x - y₀|`
exact h
Equations
Instances For
pull c rewrites the goal by pulling the constant c closer to the head of the expression.
For instance, pull _ ∈ _ rewrites x ∈ y ∨ ¬ x ∈ z into x ∈ y ∪ zᶜ.
More precisely, the pull tactic repeatedly rewrites an expression by applying lemmas
of the form ... (c ...) = c ... (where c can appear 1 or more times on the left hand side).
pull is the inverse tactic to push. To extend the pull tactic, you can tag a lemma
with the @[push] attribute. pull works as both a tactic and a conv tactic.
A lemma is considered a pull lemma if its reverse direction is a push lemma
that actually moves the given constant away from the head. For example
not_or : ¬ (p ∨ q) ↔ ¬ p ∧ ¬ qis apulllemma, butnot_not : ¬ ¬ p ↔ pis not.log_mul : log (x * y) = log x + log yis apulllemma, butlog_abs : log |x| = log xis not.Pi.mul_def : f * g = fun (i : ι) => f i * g iandPi.one_def : 1 = fun (x : ι) => 1are bothpulllemmas forfun, because everypush fun _ ↦ _lemma is also considered apulllemma.
TODO: define a @[pull] attribute for tagging pull lemmas that are not push lemmas.
pull _ ~ _pulls the operator or relation~.pull c at l1 l2 ...rewrites at the given locations.pull c at *rewrites at all hypotheses and the goal.pull (disch := tac) cuses the tactictacto discharge any hypotheses for@[push]lemmas.
Examples:
pull _ ∈ _rewritesx ∈ y ∨ ¬ x ∈ zintox ∈ y ∪ zᶜ.pull (disch := positivity) Real.logrewriteslog a + 2 * log bintolog (a * b ^ 2).pull fun _ ↦ _rewritesf ^ 2 + 5intofun x => f x ^ 2 + 5wherefis a function.
Equations
Instances For
push c rewrites the goal by pushing the constant c deeper into an expression.
For instance, push _ ∈ _ rewrites x ∈ {y} ∪ zᶜ into x = y ∨ ¬ x ∈ z.
More precisely, the push tactic repeatedly rewrites an expression by applying lemmas
of the form c ... = ... (c ...) (where c can appear 0 or more times on the right hand side).
To extend the push tactic, you can tag a lemma of this form with the @[push] attribute.
To instead move a constant closer to the head of the expression, use the pull tactic.
push works as both a tactic and a conv tactic.
push _ ~ _pushes the (binary) operator~,push ~ _pushes the (unary) operator~.push c at l1 l2 ...rewrites at the given locations.push c at *rewrites at all hypotheses and the goal.push (disch := tac) cuses the tactictacto discharge any hypotheses for@[push]lemmas.
Examples:
push _ ∈ _rewritesx ∈ {y} ∪ zᶜintox = y ∨ ¬ x ∈ z.push (disch := positivity) Real.logrewriteslog (a * b ^ 2)intolog a + 2 * log b.push ¬ _is the same aspush_negorpush Not, and it rewrites¬ ∀ ε > 0, ∃ δ > 0, δ < εinto∃ ε > 0, ∀ δ > 0, ε ≤ δ.push fun _ ↦ _rewritesfun x => f x ^ 2 + 5intof ^ 2 + 5push ∀ _, _rewrites∀ a, p a ∧ q ainto(∀ a, p a) ∧ (∀ a, q a).
Equations
Instances For
push_neg rewrites the goal by pushing negations deeper into an expression.
For instance, the goal ¬ ∀ x, ∃ y, x ≤ y will be transformed by push_neg into
∃ x, ∀ y, y < x. Binder names are preserved (contrary to what would happen with simp
using the relevant lemmas). push_neg works as both a tactic and a conv tactic.
push_neg is a special case of the more general push tactic, namely push Not.
The push tactic can be extended using the @[push] attribute. push has special-casing
built in for push Not.
Tactics that introduce a negation usually have a version that automatically calls push_neg on
that negation. These include by_cases!, contrapose! and by_contra!.
push_neg at l1 l2 ...rewrites at the given locations.push_neg at *rewrites at each hypothesis and the goal.push_neg +distribrewrites¬ (p ∧ q)into¬ p ∨ ¬ q(by default, the tactic rewrites it intop → ¬ qinstead).
Example:
example (h : ¬ ∀ ε > 0, ∃ δ > 0, ∀ x, |x - x₀| ≤ δ → |f x - y₀| ≤ ε) :
∃ ε > 0, ∀ δ > 0, ∃ x, |x - x₀| ≤ δ ∧ ε < |f x - y₀| := by
push_neg at h
-- Now we have the hypothesis `h : ∃ ε > 0, ∀ δ > 0, ∃ x, |x - x₀| ≤ δ ∧ ε < |f x - y₀|`
exact h
Equations
Instances For
#push head e, where head is a constant and e is an expression,
prints the push head form of e.
#push understands local variables, so you can use them to introduce parameters.
Equations
Instances For
#push_neg e, where e is an expression,
prints the push_neg form of e.
#push_neg understands local variables, so you can use them to introduce parameters.
Equations
Instances For
pull c rewrites the goal by pulling the constant c closer to the head of the expression.
For instance, pull _ ∈ _ rewrites x ∈ y ∨ ¬ x ∈ z into x ∈ y ∪ zᶜ.
More precisely, the pull tactic repeatedly rewrites an expression by applying lemmas
of the form ... (c ...) = c ... (where c can appear 1 or more times on the left hand side).
pull is the inverse tactic to push. To extend the pull tactic, you can tag a lemma
with the @[push] attribute. pull works as both a tactic and a conv tactic.
A lemma is considered a pull lemma if its reverse direction is a push lemma
that actually moves the given constant away from the head. For example
not_or : ¬ (p ∨ q) ↔ ¬ p ∧ ¬ qis apulllemma, butnot_not : ¬ ¬ p ↔ pis not.log_mul : log (x * y) = log x + log yis apulllemma, butlog_abs : log |x| = log xis not.Pi.mul_def : f * g = fun (i : ι) => f i * g iandPi.one_def : 1 = fun (x : ι) => 1are bothpulllemmas forfun, because everypush fun _ ↦ _lemma is also considered apulllemma.
TODO: define a @[pull] attribute for tagging pull lemmas that are not push lemmas.
pull _ ~ _pulls the operator or relation~.pull c at l1 l2 ...rewrites at the given locations.pull c at *rewrites at all hypotheses and the goal.pull (disch := tac) cuses the tactictacto discharge any hypotheses for@[push]lemmas.
Examples:
pull _ ∈ _rewritesx ∈ y ∨ ¬ x ∈ zintox ∈ y ∪ zᶜ.pull (disch := positivity) Real.logrewriteslog a + 2 * log bintolog (a * b ^ 2).pull fun _ ↦ _rewritesf ^ 2 + 5intofun x => f x ^ 2 + 5wherefis a function.
Equations
Instances For
The syntax is #pull head e, where head is a constant and e is an expression,
which will print the pull head form of e.
#pull understands local variables, so you can use them to introduce parameters.