Zulip Chat Archive

Stream: general

Topic: eliminating complex existensial


Bernd Losert (Dec 05 2021 at 12:30):

Why doesn't match ... with work here?

constants p q r : Prop
constant h : exists (a b c : α), p  q  r

def foo : exists a b c, p  q  r :=
  match h with a, b, c, prfp, prfq, prfr :=
    a, b, c, prfp, prfq, prfr
  end

Eric Wieser (Dec 05 2021 at 12:35):

What's the error?

Bernd Losert (Dec 05 2021 at 12:39):

Ah, I forgot to write exists (a b c : α) in foo.

Bernd Losert (Dec 05 2021 at 12:41):

That was a toy example. In the real code, I'm getting:

invalid constructor ...⟩, 'or' must have only one constructor

Bernd Losert (Dec 05 2021 at 12:42):

Oops. Actually, it's this error:

error: invalid constructor ...⟩, expected type is not an inductive type
  ?m_1

Huỳnh Trần Khanh (Dec 05 2021 at 12:42):

oh oops... is the problem resolved now or do you still need our help?

Bernd Losert (Dec 05 2021 at 12:43):

Yes, I still need some help. What does that last error mean?

Huỳnh Trần Khanh (Dec 05 2021 at 12:45):

ah that error simply means lean can't infer the type

Bernd Losert (Dec 05 2021 at 12:45):

By the way, this is the code that produces the error:

      (assume h, match h with x, l, hm, hf, hc :=
        or.inr x, l, hm, hf, hc
      end)

Now, it should an error since hm is not entirely correct, but it seems that the error I'm getting is more fundamental.

Eric Wieser (Dec 05 2021 at 12:46):

Can you make a #mwe? That last post is useless without knowing what the type of your goal state is

Eric Wieser (Dec 05 2021 at 12:46):

Which is to say, the humans on Zulip are also unable to infer the type

Bernd Losert (Dec 05 2021 at 12:47):

The mwe I came up with worked. Let me play around some more. The goal was to produce this:

l₁  pure y   (x : α) (l : filter α), l₁  map f l  y = f x  conv l x

Eric Wieser (Dec 05 2021 at 12:48):

Are you aware of tactic#extract_goal, which can be used as a starting point to create a mwe?

Huỳnh Trần Khanh (Dec 05 2021 at 12:48):

oh ouch this poor human being can't help you... can you just make a complete lean file with imports and stuff to demonstrate the problem and post it here OR you can just paste the file you're working on if it's short enough

Bernd Losert (Dec 05 2021 at 12:50):

Eric Wieser said:

Are you aware of tactic#extract_goal, which can be used as a starting point to create a mwe?

Interesting. Didn't know about that.

Bernd Losert (Dec 05 2021 at 12:51):

Here's the full file:

import order.filter.ultrafilter
import order.filter.partial
import algebra.support

noncomputable theory
open set filter classical
open_locale classical filter

universes u v w
variables {α β : Type*}

class convergence_space (α : Type u) :=
(conv : filter α  α  Prop)
(pure_conv :  {x : α}, conv (pure x) x)
(le_conv :  {x : α} {l l' : filter α}, l  l'  conv l' x  conv l x) -- l ≤ l' means l' ⊆ l
(sup_conv :  {x : α} {l l' : filter α}, conv l x  conv l' x  conv (l  l') x) -- l ⊔ l' means l ∩ l'

open convergence_space

def lim [convergence_space α] (l : filter α) : set α := set_of (conv l)

structure continuous [convergence_space α] [convergence_space β] (f : α  β) : Prop :=
(filter_conv :  {x : α} {l : filter α}, conv l x  conv (map f l) (f x))

class hausdorff_space [convergence_space α] : Prop :=
(hausdorff_prop :  (l : filter α) [ne_bot l], subsingleton (lim l))

def induced (f : α  β) (t : convergence_space β) : convergence_space α := {
  conv := λ l x, conv (map f l) (f x),
  pure_conv := begin
    intro,
    simp [filter.map_pure],
    apply pure_conv
  end,
  le_conv := begin
    intros x l l' h₀ h₁,
    have h₂ : map f l  map f l',
      apply map_mono h₀,
    apply le_conv h₂ h₁
  end,
  sup_conv := begin
    intros x l l' h₀ h₁,
    simp [map_sup],
    apply sup_conv h₀ h₁,
  end
}

def coinduced (f : α  β) (t : convergence_space α) : convergence_space β := {
  conv := λ l' y, l'  pure y  ( x l, l'  map f l  y = f x  conv l x),
  pure_conv := begin
    intro,
    simp [and.left]
  end,
  le_conv := begin
    intros y l₁ l₂ h₀ h₁,
    apply or.elim h₁
      (assume h, or.inl (trans h₀ h))
      (assume h, match h with x, l, hm, hf, hc :=
        or.inr x, l, trans h₀ hm, hf, hc -- THIS IS WHERE IT FAILS
      end)
  end,
  sup_conv := sorry
}

Eric Wieser (Dec 05 2021 at 12:54):

Replace apply with exact

Bernd Losert (Dec 05 2021 at 12:55):

Haha. It works. Nice.

Bernd Losert (Dec 05 2021 at 12:56):

So what's the difference between exact, apply and refine? I was using refine before, then switched to apply. And now I am switching to exact.

Eric Wieser (Dec 05 2021 at 12:56):

exact tells the elaborator "parse this expression with the knowledge that it must match the goal". apply doesn't know whether the expression is intended to exactly or partially match the goal, which can confuse the elaborator.

Eric Wieser (Dec 05 2021 at 12:57):

refine is like exact but won't error if there are _s it can't fill. You should use exact instead of refine if it's the last line of your (sub)proof

Eric Wieser (Dec 05 2021 at 12:57):

apply foo x is like refine foo x _ _ which tries to guess how many _s are needed. It's this guessing that can misfire and causes your problem

Bernd Losert (Dec 05 2021 at 12:58):

OK, so I will stick with exact as much as I can then.

Bernd Losert (Dec 05 2021 at 12:59):

Thanks guys.

Reid Barton (Dec 05 2021 at 14:51):

More specifically, exact foo knows the expected type of foo (namely the goal) and can use this to elaborate foo, while apply foo doesn't know the expected type of foo because it will be foo _ ... _ that matches the goal; so apply needs to first elaborate foo without expected type information to work out the correct number of _s, and here it has no way to know what the anonymous constructor ⟨x, l, trans h₀ hm, hf, hc⟩ refers to.

Reid Barton (Dec 05 2021 at 14:55):

We rarely use match or apply eliminators directly in tactics, a more tactic-style proof would be

  le_conv := begin
    intros y l₁ l₂ h₀ h₁,
    rcases h₁ with h | x, l, hm, hf, hc⟩,
    { exact or.inl (trans h₀ h) },
    { exact or.inr x, l, trans h₀ hm, hf, hc }
  end,

or variants using tactic#rintro or tactic#obtain

Eric Wieser (Dec 05 2021 at 15:17):

Reid Barton said:

so apply needs to first elaborate foo without expected type information to work out the correct number of _s

Is there a reason apply doesn't just try elaborating foo, foo _, foo _ _, ... until it finds one that matches, as opposed to elaborating foo with incomplete information?


Last updated: Dec 20 2023 at 11:08 UTC