Zulip Chat Archive

Stream: new members

Topic: How to manipulate proofs that involve Sigma types


kroton (Aug 02 2025 at 10:27):

Hello,
I got stuck in the middle of a proof when I encountered the following situation.
I tried using grind, which improved things, but is it possible to resolve this manually?

example {I : Type*} {β : I  Type*} {S : (i : I)  Set (β i)}
  (f : (i : I)  Σ i, β i)
  (h1 :  i, (f i).fst = i)
  (h2 :  i, (f i).snd  S (f i).fst)
:  i, (h1 i)  (f i).snd  S i := by
  grind

Eric Wieser (Aug 02 2025 at 10:40):

intro i; specialize h1 i; specialize h2 i; cases h1; exact h2?

kroton (Aug 02 2025 at 10:48):

@Eric Wieser
Thanks for your reply.
However, in my environment, it failed with the following error.

dependent elimination failed, failed to solve equation
  i = (f i).fst

Eric Wieser (Aug 02 2025 at 11:09):

My mental Lean environment has some bugs

Eric Wieser (Aug 02 2025 at 11:10):

You'll need to generalize h : f i =fi at * first or similar

suhr (Aug 02 2025 at 11:19):

Played with it a little:

import Mathlib

example {I : Type*} {β : I  Type*} {S : (i : I)  Set (β i)}
  (f : (i : I)  Σ i, β i)
  (h1 :  i, (f i).fst = i)
  (h2 :  i, (f i).snd  S (f i).fst)
:  i, (h1 i)  (f i).snd  S i := by
  intro i
  suffices h: (h3: (f i).fst = i)  (h4: (f i).snd  S (f i).fst)  h3  (f i).snd  S i
  from (h (h1 i) (h2 i))
  refine (f i).recOn ?_
  dsimp
  intro j h1 h2 h3
  sorry

The Σ type is not a problem, but an is.

kroton (Aug 02 2025 at 11:26):

@Eric Wieser
generalize also failed with a different error in my environment .

tactic 'generalize' failed, result is not type correct
  ∀ (fi : (i : I) × β i), ⋯ ▸ fi.snd ∈ S i

suhr (Aug 02 2025 at 11:28):

By the way, you can just look at the proof generated by grind:

import Mathlib

def foo {I : Type*} {β : I  Type*} {S : (i : I)  Set (β i)}
  (f : (i : I)  Σ i, β i)
  (h1 :  i, (f i).fst = i)
  (h2 :  i, (f i).snd  S (f i).fst)
:  i, (h1 i)  (f i).snd  S i := by grind

#print foo
#print foo._proof_1

It's weird but short, so could be refactored into something readable.

kroton (Aug 02 2025 at 11:32):

@suhr
Thanks for your reply.
I didn’t know that it was possible to see the result of grind—thank you!

kroton (Aug 02 2025 at 13:02):

I tried checking what grind does, but just copy-pasting it doesn’t seem to work.
I asked ChatGPT too, but didn’t get anything useful. Hmm...

theorem foo._proof_3.{u_1, u_2} :  {I : Type u_2} {β : I  Type u_1} {S : (i : I)  Set (β i)} (f : I  (i : I) × β i)
  (h1 :  (i : I), (f i).fst = i), ( (i : I), (f i).snd  S (f i).fst)   (i : I), h1 i  (f i).snd  S i :=
fun {I} {β} {S} f h1 h2 i 
  Classical.byContradiction fun h 
    Eq.mp
      (Eq.trans
        (Eq.trans (Eq.symm (eq_true (Eq.mp (Eq.refl ((f i).snd  S (f i).fst)) (h2 i))))
          (eq_of_heq
            (Membership.mem.hcongr_5 (β (f i).fst) (β i) (congrArg β (h1 i)) (Set (β (f i).fst)) (Set (β i))
              (congrArg (fun x  Set (β x)) (h1 i)) Set.instMembership Set.instMembership
              (Set.instMembership.hcongr_1 (β (f i).fst) (β i) (congrArg β (h1 i))) (S (f i).fst) (S i)
              ((fun i i' e_1  e_1  HEq.refl (S i)) (f i).fst i (h1 i)) (f i).snd ((f i).fst = i  (f i).snd)
              (HEq.symm (Lean.Grind.eqRec_heq (f i).snd (f i).fst = i)))))
        (eq_false h))
      True.intro

kroton (Aug 02 2025 at 13:03):

The error occurs at the expression e₁ ▸ HEq.refl (S i) in the code above.

Eric Wieser (Aug 02 2025 at 13:11):

Note that instead of using #print after the proof, you can use show_term grind inside it

suhr (Aug 02 2025 at 13:12):

import Mathlib

theorem foobar.{u_1, u_2} :  {I : Type u_2} {β : I  Type u_1} {S : (i : I)  Set (β i)} (f : I  (i : I) × β i)
  (h1 :  (i : I), (f i).fst = i), ( (i : I), (f i).snd  S (f i).fst)   (i : I), h1 i  (f i).snd  S i :=
fun {I} {β} {S} f h1 h2 i =>
  Classical.byContradiction fun h =>
    Eq.mp
      (Eq.trans
        (Eq.trans (Eq.symm (eq_true (Eq.mp (Eq.refl ((f i).snd  S (f i).fst)) (h2 i))))
          (eq_of_heq
            (Membership.mem.hcongr_5 (β (f i).fst) (β i) (congrArg β (h1 i)) (Set (β (f i).fst)) (Set (β i))
              (congrArg (fun x => Set (β x)) (h1 i)) Set.instMembership Set.instMembership
              (Set.instMembership.hcongr_1 (β (f i).fst) (β i) (congrArg β (h1 i))) (S (f i).fst) (S i)
              ((fun i i' e_1 => @Eq.ndrec I i (fun i' => S i  S i') (HEq.refl (S i)) i' e_1) (f i).fst i (h1 i)) (f i).snd (@Eq.rec I (f i).fst (fun x h => β x) (f i).snd i (h1 i))
              (HEq.symm (eqRec_heq (h1 i) (f i).snd)))))
        (eq_false h))
      True.intro

suhr (Aug 02 2025 at 13:13):

Obtained using clicking in the lean infoview and by apply?.

kroton (Aug 02 2025 at 13:23):

@Eric Wieser @suhr
Thank you for your response. I’ll do a bit more digging.

Aaron Liu (Aug 02 2025 at 13:27):

It's not that complicated and you can just do it manually

import Mathlib

example {I : Type*} {β : I  Type*} {S : (i : I)  Set (β i)}
    (f : (i : I)  Σ i, β i)
    (h1 :  i, (f i).fst = i)
    (h2 :  i, (f i).snd  S (f i).fst) :
     i, (h1 i)  (f i).snd  S i :=
  fun i => Eq.rec (motive := fun x h => h  (f i).snd  S x) (h2 i) (h1 i)

suhr (Aug 02 2025 at 13:27):

Beware of dependent type hell. Heterogeneous equality is famously poorly behaving in Lean. It would be wise to avoid it.

Aaron Liu (Aug 02 2025 at 13:31):

In general dependent rewriting is hard tedious but this case is simple so you get a relatively simple solution

suhr (Aug 02 2025 at 13:32):

Yeah. An elegant usage of Eq.rec by the way, you rarely see the second argument being used.

kroton (Aug 02 2025 at 13:38):

@Aaron Liu Wow, thanks for the simple solution!


Last updated: Dec 20 2025 at 21:32 UTC