Zulip Chat Archive

Stream: lean4

Topic: let in statement


Jon Eugster (Mar 14 2024 at 22:39):

I have a couple of teaching exercises (in a NNG-like game) about concretely defined functions and currenctly I use the following syntax for the locally defined function f:

-- import Mathlib  -- optional

example : let f : Nat  Nat := fun x  2 * x; f 4 = 8 := by
  intro f
  -- the actual exercise starts:
  rfl

I prefer this over def f := because

a) it's visible in the context (a player does only see the context, not the code before the exercise) and
b) it does not pollute any namespace with random defs.

What I dislike is that they are forced to always enter intro f as a first step and until then the goal looks rather taunting.

Does anybody have a better idea how I could write a statement such that the start of the proof is in a similar state to what it looks like after intro f currently?

f: Nat  Nat := fun x => 2 * x
 f 4 = 8

Or maybe more concretely, what does intro f exactly do at this stage?

Could I achieve this in meta-code since I already replaced example by a custom elab "Statement" sig:declSig val:declVal : command => do _ which then calls elabCommand eventually (see here)

Patrick Massot (Mar 14 2024 at 22:52):

Sure, you could put your intro in your custom command.

Eric Wieser (Mar 14 2024 at 22:55):

It would be nice if theorem foo (x : Nat) (let f := _) (h : f x < 2) or similar were legal

Jon Eugster (Mar 14 2024 at 23:08):

Patrick Massot said:

Sure, you could put your intro in your custom command.

But if I dont know how many lets there are (0 or more) and I dont want to intro anything else (like a \forall following the let), it's not quite as simple, is it?

Jon Eugster (Mar 14 2024 at 23:09):

Eric Wieser said:

It would be nice if theorem foo (x : Nat) (let f := _) (h : f x < 2) or similar were legal

Would you estimate that's something one could make legal with the required meta-coding skills?:thinking:

Patrick Massot (Mar 14 2024 at 23:12):

You would need a intro_lets tactic.

Patrick Massot (Mar 14 2024 at 23:12):

This should be pretty easy.

Jon Eugster (Mar 14 2024 at 23:13):

You do have a point

Eric Wieser (Mar 14 2024 at 23:30):

Jon Eugster said:

Eric Wieser said:

It would be nice if theorem foo (x : Nat) (let f := _) (h : f x < 2) or similar were legal

Would you estimate that's something one could make legal with the required meta-coding skills?:thinking:

I think this probably would be much easier as a core change; I think extending existing syntax externally is quite awkward.

Eric Wieser (Mar 14 2024 at 23:37):

It might at least be worth writing an rfc

Jon Eugster (Mar 15 2024 at 10:42):

Patrick Massot said:

You would need a intro_lets tactic.

Indeed, after realising what I need to do it wasn't that complicated:

let_intros

This introduces all let statements:

example (f : Nat) :
    let f := fun x  x + 1
    let g : Nat  Nat := fun y  y
     x : Nat, x  f x := by
  let_intros
  /-
  f✝ : Nat
  f : Nat → Nat := fun x => x + 1
  g : Nat → Nat := fun y => y
  ⊢ ∀ (x : Nat), x ≤ f x
  -/
  intro x
  exact Nat.le_succ x

Thanks for the hint!

Kyle Miller (Mar 15 2024 at 14:58):

The extract_lets tactic theoretically supports this, but apparently extract_lets at ⊢ is a parse error because there are zero hypotheses. You can still use it, if you create syntax with zero hypotheses:

elab "let_intros" (ppSpace colGt (ident <|> hole))* : tactic => do
  Lean.Elab.Tactic.evalTactic <|  `(tactic| extract_lets at $(#[])* )

If you wanted to make a PR to make the location clause optional for extract_lets, then you could have extract_lets act just on the goal.

Or maybe you could add let_intros to that file for acting on just the goal? The extract_lets command is meant to be for hypotheses anyway, and it's not a good name for acting on the goal.

This is the meta implementation for acting on the goal: docs#Lean.MVarId.extractLets And this is the tactic driver: docs#Mathlib.evalExtractLet

Jon Eugster (Mar 15 2024 at 16:59):

#11400 cleans up extract_lets.

(I don't have any opinion on the tactic naming, so I just left it as is.)

Eric Wieser (Nov 15 2024 at 14:22):

Eric Wieser said:

It would be nice if theorem foo (x : Nat) (let f := _) (h : f x < 2) or similar were legal

I made an RFC for this at lean4#6091


Last updated: May 02 2025 at 03:31 UTC