Zulip Chat Archive

Stream: general

Topic: Convert Divisibility Hypothesis to pexpr


Aaron Bryce (May 23 2019 at 06:37):

I've come across an issue with a tactic I'm trying to write, which needs to have different behaviour based on the divisibility of the inputs, and I need to be able to convert the hypothesis generated by the if statement into a pexpr (or expr as the conversion between the two is not an issue) to use later in the tactic.

/-- If `x ∣ y` return an `expr` containing a proof! -/ meta def baz (x y : ℕ) : tactic (option expr) := if h : x ∣ y then some <$> to_expr ``(reflect %%h) else pure none

The above code currently errors with, failed to find type class instance for has_to_pexpr (x ∣ y). Does anyone know if this instance exists and just can't be inferred correctly, a way to make this instance if it doesn't exist, or an alternative way to convert the hypothesis to a (p)expr?

Mario Carneiro (May 23 2019 at 06:43):

It is not possible to do what you are attempting, because h does not exist in the VM

Scott Morrison (May 23 2019 at 06:43):

:-(

Mario Carneiro (May 23 2019 at 06:43):

Instead, you merely learn from that if statement that in fact x divides y, without a proof

Mario Carneiro (May 23 2019 at 06:44):

You can try to produce a proof by using dec_trivial

Mario Carneiro (May 23 2019 at 06:44):

by norm_num is probably the best method

Scott Morrison (May 23 2019 at 06:45):

Oh, I see. You have the if statement that is executed in the tactic logic, and then when it's time to build the expr you're after, you build the proof again inside a quotation.

Scott Morrison (May 23 2019 at 06:48):

Is this doing it?

open tactic

/-- If `x ∣ y` return an `expr` containing a proof! -/
meta def baz (x y : ℕ) : tactic (option expr) :=
if h : x ∣ y then
  some <$> to_expr ``(by norm_num : %%(reflect x) ∣ %%(reflect y))
else
  pure none

Mario Carneiro (May 23 2019 at 06:51):

/-- If `x ∣ y` return an `expr` containing a proof! -/
meta def baz (x y : ) : tactic (option expr) :=
if x  y then do
  (_, p)  norm_num.derive `((%%(reflect x) : )  %%(reflect y)),
  p'  tactic.mk_eq_mpr p `(trivial),
  return (some p')
else
pure none

run_cmd do
  some e <- baz 2 6, tactic.infer_type e >>= tactic.trace

Mario Carneiro (May 23 2019 at 06:52):

you build the proof again

You never built a proof the first time. For all you know the reason x | y evaluated to true is because it evaluated it with GMP natural numbers

Scott Morrison (May 23 2019 at 06:53):

Huh. Okay!

Scott Morrison (May 23 2019 at 06:53):

Lean is awesome. :-)

Aaron Bryce (May 23 2019 at 06:55):

Indeed. Both dec_trivial and norm_num seem to work in this instance, this tactic is now appears to be fully working Scott.


Last updated: Dec 20 2023 at 11:08 UTC