Zulip Chat Archive

Stream: general

Topic: Pass local hypotheses to tactic


Abhimanyu Pallavi Sudhir (Jan 24 2019 at 18:27):

Is this how I make a tactic that requires a local hypothesis (represented variously by p, e, and H1)?

import analysis.normed_space
open lean lean.parser tactic interactive interactive.types expr

meta def unfold_eps_del_1 (  fx :   )
(p1 : parse texpr) : tactic unit := do e  i_to_expr p1, let H1 := expr.get_app_fn e,
`[try {simp only [filter.tendsto_nhds_of_metric, dist], rw sub_zero}],
`[try {simp only [filter.tendsto_punctured]}],
`[try {simp only [filter.tendsto_nhds_of_metric, dist] at H1, rw sub_zero at H1}],
`[try {simp only [filter.tendsto_punctured] at H1}],
`[intros ε ε0],
`[have H11 := H1 ( ε) _],
`[cases H11 with δ H12],
`[cases H12 with  H13],
`[existsi ( δ)],
`[existsi _],
`[intros x xd],
`[try {intro x0}],
`[have H14 := H13 (fx x) _],
`[try {have H15 := H14 _}]

I'm basing this on the code for meta def specialize in library/init/meta/interactive.lean but not sure how it works.

Abhimanyu Pallavi Sudhir (Jan 24 2019 at 18:46):

Is this right?

Abhimanyu Pallavi Sudhir (Jan 24 2019 at 18:46):

import analysis.normed_space
open lean lean.parser tactic interactive interactive.types expr

meta def unfold_eps_del_1 (  fx :   )
(p : parse ident) : tactic unit := do H1  resolve_name p,
`[try {simp only [filter.tendsto_nhds_of_metric, dist], rw sub_zero}],
`[try {simp only [filter.tendsto_punctured]}],
`[try {simp only [filter.tendsto_nhds_of_metric, dist] at H1, rw sub_zero at H1}],
`[try {simp only [filter.tendsto_punctured] at H1}],
`[intros ε ε0],
`[have H11 := H1 ( ε) _],
`[cases H11 with δ H12],
`[cases H12 with  H13],
`[existsi ( δ)],
`[existsi _],
`[intros x xd],
`[try {intro x0}],
`[have H14 := H13 (fx x) _],
`[try {have H15 := H14 _}]

Abhimanyu Pallavi Sudhir (Jan 24 2019 at 18:49):

It seems right, but when I try to actually use the tactic by giving it the name of a hypothesis, it fails saying unknown identifier 'a':

def has_derivative_at (f :   ) (x0 : ) (f'x0 : )
:= (tendsto (λ h, (f (x0 + h) - f (x0) - f'x0 * h)/h) (nhds 0) (nhds 0))

lemma has_derivative_at_iff_eps_del (f :   ) (x0 : ) (f'x0 : )
: has_derivative_at f x0 f'x0 
   ε > 0,  δ > 0,  h : , abs h < δ  abs ((f(x0 + h) - f(x0) - f'x0 * h) / h) < ε
  := by simp [has_derivative_at, tendsto_nhds_of_metric, dist]

lemma has_derivative_at_iff_eps_del' (f :   ) (x0 : ) (f'x0 : )
: has_derivative_at f x0 f'x0 
   ε > 0,  δ > 0,  h : , h  0  abs h < δ  abs ((f(x0 + h) - f(x0))/h - f'x0) < ε :=
begin
  split,
  { intro a, rw has_derivative_at_iff_eps_del at a,
    unfold_eps_del_1 id id id a,
  }
end

And when I try this:

lemma has_derivative_at_iff_eps_del' (f :   ) (x0 : ) (f'x0 : )
: has_derivative_at f x0 f'x0 
   ε > 0,  δ > 0,  h : , h  0  abs h < δ  abs ((f(x0 + h) - f(x0))/h - f'x0) < ε :=
begin
  split,
  { intro a, rw has_derivative_at_iff_eps_del at a,
    unfold_eps_del_1 id id id "a",
  }
end

I get unknown identifier 'H1', so I must be doing something wrong.

Patrick Massot (Jan 24 2019 at 20:12):

Did you read https://github.com/leanprover/mathlib/blob/master/docs/extras/tactic_writing.md?

Abhimanyu Pallavi Sudhir (Jan 24 2019 at 20:36):

I hadn't seen that -- so I guess get_local is the right command (as opposed to resolve_name)? But this doesn't work either:

import analysis.normed_space
open lean tactic interactive.types expr
open interactive (parse)
open lean.parser (ident)

meta def unfold_eps_del_1 (  fx :   )
(p : parse ident) : tactic unit := do H1  get_local p,
`[try {simp only [filter.tendsto_nhds_of_metric, dist], rw sub_zero}],
`[try {simp only [filter.tendsto_punctured]}],
`[try {simp only [filter.tendsto_nhds_of_metric, dist] at H1, rw sub_zero at H1}],
`[try {simp only [filter.tendsto_punctured] at H1}],
`[intros ε ε0],
`[have H11 := H1 ( ε) _],
`[cases H11 with δ H12],
`[cases H12 with  H13],
`[existsi ( δ)],
`[existsi _],
`[intros x xd],
`[try {intro x0}],
`[have H14 := H13 (fx x) _],
`[try {have H15 := H14 _}]

def has_derivative_at (f :   ) (x0 : ) (f'x0 : )
:= (tendsto (λ h, (f (x0 + h) - f (x0) - f'x0 * h)/h) (nhds 0) (nhds 0))

lemma has_derivative_at_iff_eps_del (f :   ) (x0 : ) (f'x0 : )
: has_derivative_at f x0 f'x0 
   ε > 0,  δ > 0,  h : , abs h < δ  abs ((f(x0 + h) - f(x0) - f'x0 * h) / h) < ε
  := by simp [has_derivative_at, tendsto_nhds_of_metric, dist]

lemma has_derivative_at_iff_eps_del' (f :   ) (x0 : ) (f'x0 : )
: has_derivative_at f x0 f'x0 
   ε > 0,  δ > 0,  h : , h  0  abs h < δ  abs ((f(x0 + h) - f(x0))/h - f'x0) < ε :=
begin
  split,
  { intro a, rw has_derivative_at_iff_eps_del at a,
    unfold_eps_del_1 id id id a,
  }
end

Rob Lewis (Jan 24 2019 at 20:41):

None of the expressions you have enclosed in `[...] refer to the fε fδ fx arguments to unfold_eps_del_1, nor to p or H1. When you write a tactic using this notation and then apply it in a proof, you can imagine that the text inside `[...] just gets copied literally into that point in the proof.

Rob Lewis (Jan 24 2019 at 20:42):

This notation is useful for very small tactic scripts. But if you want to write a tactic that takes parameters, you really need to learn "non-interactive" tactic mode.


Last updated: Dec 20 2023 at 11:08 UTC