Zulip Chat Archive
Stream: lean4
Topic: How to refer to unnamed proofs in term mode?
Mario Weitzer (Nov 12 2025 at 13:16):
This is a very basic question but how can I avoid using tactic mode in a proof like this one:
lemma l1 (n : Nat) (_ : n = 0) : n = 0 := by
assumption
lemma l2 (n : Nat) (_ : n = 0) : n = 0 := by
expose_names
exact h
lemma l3 (n : Nat) (_ : n = 0) : n = 0 := by
revert n
exact fun n h => h
#print l1
-- theorem l1 : ∀ (n : Nat), n = 0 → n = 0 := fun n x ↦ x
#print l2
-- theorem l2 : ∀ (n : Nat), n = 0 → n = 0 := fun n x ↦ x
#print l3
-- theorem l3 : ∀ (n : Nat), n = 0 → n = 0 := fun n x ↦ x
lemma l4 (n : Nat) (_ : n = 0) : n = 0 := fun n x ↦ x
-- Doesn't work for obvious reasons, even though it's just a copy of what #print claims to be the proof term of l1, l2, and l3.
Michael Rothgang (Nov 12 2025 at 13:27):
If you want to refer to the hypothesis on n, you should give it a name (not just an underscore).
Michael Rothgang (Nov 12 2025 at 13:28):
#print doesn't say "it's unnamed", by the way (it wouldn't print names for named arguments either, but prints the type of the statement).
Mario Weitzer (Nov 12 2025 at 14:30):
Michael Rothgang said:
#print doesn't say "it's unnamed", by the way (it wouldn't print names for named arguments either, but prints the type of the statement).
I know that giving it a name would solve the problem but this is just a minimal example of an artificial situation in which I don't have a name, which can occur in some situations. For example, it's not common to give names to type class instances (even though I'm aware that it is possible to name them as well)
lemma l5 (n : Nat) [Fact (n = 0)] : n = 0 := by
exact Fact.elim (by assumption)
#print l5
-- l5 : ∀ (n : Nat) [Fact (n = 0)], n = 0 := fun n [inst : Fact (n = 0)] ↦ Fact.elim inst
There must be a way to complete these proofs without going into tactic mode, isn't there?
Damiano Testa (Nov 12 2025 at 14:36):
Would using exact?% be a solution? :upside_down:
Jovan Gerbscheid (Nov 12 2025 at 14:37):
Here are some of the ways you might do this:
import Mathlib
example (n : Nat) [Fact (n = 0)] : n = 0 := by
exact Fact.elim ‹Fact (n = 0)›
example (n : Nat) [Fact (n = 0)] : n = 0 := by
exact Fact.elim inferInstance
example (n : Nat) [Fact (n = 0)] : n = 0 := by
expose_names
exact Fact.elim inst
example (n : Nat) [Fact (n = 0)] : n = 0 := by
rename_i bla
exact Fact.elim bla
Mario Weitzer (Nov 12 2025 at 14:42):
Jovan Gerbscheid said:
Here are some of the ways you might do this:
import Mathlib example (n : Nat) [Fact (n = 0)] : n = 0 := by exact Fact.elim ‹Fact (n = 0)› example (n : Nat) [Fact (n = 0)] : n = 0 := by exact Fact.elim inferInstance example (n : Nat) [Fact (n = 0)] : n = 0 := by expose_names exact Fact.elim inst example (n : Nat) [Fact (n = 0)] : n = 0 := by rename_i bla exact Fact.elim bla
Yes, but all of these use tactics. I want to prove it without going into tactic mode (so no "by" anywhere).
Yaël Dillies (Nov 12 2025 at 14:42):
The exact term mode equivalent of assumption is ‹_›
Jovan Gerbscheid (Nov 12 2025 at 14:42):
The first two options work in term mode
Yaël Dillies (Nov 12 2025 at 14:43):
In general, ‹Foo› is the same as (by assumption : Foo)
Mario Weitzer (Nov 12 2025 at 14:44):
Yaël Dillies said:
The exact term mode equivalent of
assumptionis‹_›
I see, thanks! (to all of you)
Ruben Van de Velde (Nov 12 2025 at 14:50):
But also the solution is usually "don't get into this situation" (i.e., name the hypothesis when you have the chance)
Damiano Testa (Nov 12 2025 at 15:18):
Isn't ‹_› a macro for by assumption, though? Does that really count as "not using tactic mode"?
Last updated: Dec 20 2025 at 21:32 UTC