Zulip Chat Archive
Stream: lean4
Topic: intro with type specified
Dan Velleman (Oct 20 2022 at 13:30):
Consider this example:
import Mathlib
example (U : Type) (A B : Set U) : A ⊆ B → A ∩ B = A := by
intro h
After intro h
, I have h : A ⊆ B
in the tactic state. But now suppose I change the example to this:
import Mathlib
example (U : Type) (A B : Set U) : A ⊆ B → A ∩ B = A := by
intro (h : A ⊆ B)
Now I get an error message: type mismatch h has type A ⊆ B : Prop but is expected to have type ?m.49 ∈ A → ?m.49 ∈ B : Prop
. Why? Shouldn't this work?
Floris van Doorn (Oct 20 2022 at 14:08):
The definition of Set.subset
is
∀ {a}, a ∈ s₁ → a ∈ s₂
and so it seems like Lean interprets h
as @h _
.
This looks like a bug in intro
(since h
should not be applied to implicit arguments).
Dan Velleman (Oct 20 2022 at 14:32):
That's what I thought. Any idea how to fix it?
Floris van Doorn (Oct 20 2022 at 15:28):
If you don't specify the type, it will work:
example (U : Type) (A B : Set U) : A ⊆ B → A = A := by
intro h
Floris van Doorn (Oct 20 2022 at 15:37):
Opened a (minimized) issue as leanprover/lean4#1759
Dan Velleman (Oct 20 2022 at 15:37):
Yes, I know. But I'm supposed to be able to specify the type, right?
I am trying to implement an assume
tactic, for use by students. My tactic is essentially just a wrapper around intro
. I want to encourage students to say explicitly what statement is being assumed, so that Lean can correct them if they are assuming the wrong thing. So I need to be able to pass the type to intro
and have it make sure it's the right type. So this bug, if it is a bug, is a problem for me.
Leonardo de Moura (Oct 20 2022 at 16:07):
Pushed a fix for the issue above.
Dan Velleman (Oct 20 2022 at 16:22):
Thanks!
Dan Velleman (Mar 19 2023 at 15:51):
I'm a little puzzled by the following examples:
import Mathlib.Data.Set.Basic
attribute [default_instance] Set.instSingletonSet
example (x y : Nat) : y ∈ {x} → y = x := by
intro h
exact h
done
example (x y : Nat) : y ∈ {x} → y = x := by
intro (h : y ∈ {x})
exact h
done
example (x y : Nat) : y ∈ {x} → y = x := by
intro (h : y ∈ ({x} : Set Nat))
exact h
done
The first and third examples work, but the second doesn't. The error message is
type mismatch at `intro h`has type
y ∈ {x} : Prop
but is expected to have type
y ∈ ?m.387 : Prop
If I don't include the line attribute [default_instance] Set.instSingletonSet
, then Lean doesn't understand the example at all. I assume the problem is that the notation {x}
becomes ambiguous because it could have several different types. With the line attribute [default_instance] Set.instSingletonSet
, Lean interprets {x}
in the statement of the example as denoting a singleton set. But it doesn't seem to understand it that way in intro
. Is the default_instance
specification ignored by intro
?
Eric Wieser (Mar 19 2023 at 16:02):
Weirdly intro (h : y ∈ singleton x)
works fine too
Kyle Miller (Mar 20 2023 at 03:07):
When I was implementing change ... at
I noticed these sorts of unification errors occurring. I don't fully understand them, but I did find a workaround by using the show
elaborator. I'll just leave this working implementation of intro
with type ascriptions here in case anyone has any ideas (note that it works without the default instance as well, after suitably modifying the theorem statements):
import Lean
import Mathlib.Data.Set.Basic
open Lean Elab Elab.Tactic Meta
def introType (n : Name) (typeStx : TSyntax `term) : TacticM Unit := do
let fvarId ← liftMetaTacticAux fun mvarId => do
let (fvarId, mvarId) ← mvarId.intro n
pure (fvarId, [mvarId])
withMainContext do
let fvarType ← fvarId.getType
let mvar ← mkFreshExprMVar none
_ ← Term.withSynthesize <|
elabTerm (← `(term | show $typeStx from $(← Term.exprToSyntax mvar))) fvarType
let type ← inferType mvar
liftMetaTactic fun mvarId => return [← mvarId.replaceLocalDeclDefEq fvarId type]
syntax "my_intro" "(" ident " : " term ")" : tactic
elab_rules : tactic
| `(tactic| my_intro ($h:ident : $type:term)) => introType h.getId type
attribute [default_instance] Set.instSingletonSet
example (x y : Nat) : y ∈ {x} → y = x := by
my_intro (h : _)
exact h
done
example (x y : Nat) : y ∈ {x} → y = x := by
my_intro (h : y ∈ {x})
exact h
done
example (x y : Nat) : y ∈ ({x} : Set Nat) → y = x := by
my_intro (h : y ∈ ({x} : Set Nat))
exact h
done
Dan Velleman (Mar 24 2023 at 13:08):
Thanks @Kyle Miller for your suggestion.
Here's another idea: Do the same thing that evalIntro
does for the pattern-matching case:
elab_rules : tactic
| `tactic| my_intro ($h:ident : $type:term)) =>
evalTactic (← `(tactic| intro h; match @h with | ($h : $type) => ?_; try clear h))
I'm not sure I entirely understand what's going on here, but it seems to work. Is there any possibility of the h
in the intro h
step conflicting with some other name? Is the try
necessary?
Patrick Massot (Jul 31 2023 at 17:44):
I know this is an old thread but I have a new question about the same topic. The context of this question is this comment where a user laments that you cannot put type ascriptions in intros
. I was about to answer that you can, but I decided to check just in case. Weirdly, you can with intro
, thanks to those lines but not with intros
(whose code is a few lines down). Is it intentional? In the spirit of getting rid of the plural versions universes
and variables
, wouldn't it make to get rid of intros
? Or is it meant to have a really different meaning?
Eric Wieser (Jul 31 2023 at 17:46):
I guess the key difference is that intros
intros all the binders but intro
intros just one? Maybe intro ..
could be the spelling for "intro everything", to match exact foo ..
to use everything; which lets us eliminate intros
.
Patrick Massot (Jul 31 2023 at 17:49):
By the way, the previous messages in this thread are also interesting and seem to be still relevant.
Patrick Massot (Jul 31 2023 at 17:49):
Eric, you can intro many things with intro
.
Patrick Massot (Jul 31 2023 at 17:50):
But indeed if you don't specify any name then intro
will intro only one, and intros
will intro everything. But this isn't very useful since you get inaccessible names.
Jireh Loreaux (Jul 31 2023 at 17:57):
the intro ..
spelling or intro a b c ..
seems nice.
Eric Wieser (Jul 31 2023 at 17:57):
Sure, my point was that if we're going to combine the two commands into one (which I agree is a good idea), then we need to disambiguate intro
from intros
when they have no arguments, either by changing the spelling of one, or dropping one entirely
Eric Wieser (Jul 31 2023 at 17:58):
I guess even intro a .. b c
could be legal
Eric Rodriguez (Aug 01 2023 at 09:23):
what is the exact ..
syntax? I see it's used a couple times in mathlib
Eric Wieser (Aug 01 2023 at 09:30):
f ..
means f _ _ _
for suitably many _
Last updated: Dec 20 2023 at 11:08 UTC