Zulip Chat Archive

Stream: general

Topic: choose and autoparams


Chris Henson (Dec 17 2025 at 07:03):

What is the cleanest way to use autoparams where you would normally use choose? E.g. if I have

import Mathlib

example (h : (k : )  (h : k < 0)   x, x = k) : True := by
  choose foo foo_spec using h
  -- foo : (k : ℕ) → k < 0 → ℕ
  -- foo_spec : ∀ (k : ℕ) (h : k < 0), foo k h = k
  sorry

what is the easiest way I can have (h : k < 0 := by grind) in the signature(s)?

Jakub Nowak (Dec 17 2025 at 07:08):

I don't understand. Could you provide an example of what you want to happen?

Chris Henson (Dec 17 2025 at 07:26):

Hmm, I'm not sure how to restate more clearly. I'd like to know the best way for instance in the above example to end up with foo : (k : ℕ) → (h : k < 0 := by grind) → ℕ and/or foo_spec : ∀ (k : ℕ) (h : k < 0 := by grind), foo k h = k, does that make sense?

Jakub Nowak (Dec 17 2025 at 07:28):

Thanks, now I understand.

Edward van de Meent (Dec 17 2025 at 08:12):

I haven't added autoparams inside a proof before, but presumably this would do it:

have h' : (k : )  (h' : k < 0 := by grind)   x, x = k := h
choose foo foo_spec using h'

Jakub Nowak (Dec 17 2025 at 08:15):

Edward van de Meent said:

I haven't added autoparams inside a proof before, but presumably this would do it:

have h' : (k : )  (h' : k < 0 := by grind)   x, x = k := h
choose foo foo_spec using h'

Nope, this doesn't work, choose evaluates autoParam too eagerly.

Jakub Nowak (Dec 17 2025 at 08:16):

But I suspect, it's possible to make choose handle autoParam so that this works.

Edward van de Meent (Dec 17 2025 at 08:20):

Wait what? What are you saying choose does here? Surely it isn't able to synthesize a proof of k < 0?

Edward van de Meent (Dec 17 2025 at 08:20):

(I'm typing from mobile)

Jakub Nowak (Dec 17 2025 at 08:21):

Yes, it fails, because it couldn't synthesize the proof of k < 0.

Chris Henson (Dec 17 2025 at 08:21):

Right, it can't synthesize a proof, but will eagerly fail to do so.

Jakub Nowak (Dec 17 2025 at 08:21):

This does what you want, but the syntax is far from perfect.

import Mathlib

structure NatWrap where
  val : 
  prop : k < 0 := by grind

instance : Coe NatWrap Nat where
  coe w := w.val

example (h : (k : NatWrap)   (x : ), x = k) : True := by
  choose foo foo_spec using h
  let x := foo (.mk 3)
  have hx := foo_spec (.mk 3)
  dsimp only at hx

Chris Henson (Dec 17 2025 at 08:49):

The above isn't working in the web editor or locally for me. Did you mean to have prop : 0 < val := by grind for this example?

Jakub Nowak (Dec 17 2025 at 09:42):

Oh, wait, you just need to write using @h, not using h and it works.

Jakub Nowak (Dec 17 2025 at 09:43):

Chris Henson said:

The above isn't working in the web editor or locally for me. Did you mean to have prop : 0 < val := by grind for this example?

It works, in the sense, that I tried to prove 3 < 0 using by grind. It failed to prove it of course.

Jakub Nowak (Dec 17 2025 at 09:44):

Ah, no, sorry, it should be val < 0, not k < 0. But you can also use 0 < val, if you want to see what happens whenby grind succeeds.

Jakub Nowak (Dec 17 2025 at 09:49):

Anyway, that is obsolete now. This does exactly what you wanted:

import Mathlib.Tactic.Choose

example (h : (k : )  (h : k < 0 := by grind)   x, x = k) : True := by
  choose foo foo_spec using @h

Jakub Nowak (Dec 17 2025 at 09:56):

What happens, is that it wasn't choose fault, that autoProp was eagerly expanded. The term h, when elaborated, already expands autoProp, that's why you need @h.

Chris Henson (Dec 17 2025 at 09:56):

This is perfect, thanks!

Chris Henson (Dec 17 2025 at 09:58):

(your explanation is good too!)


Last updated: Dec 20 2025 at 21:32 UTC