Zulip Chat Archive
Stream: mathlib4
Topic: dec_trivial with metavariables
David Ang (Jun 21 2023 at 20:03):
What's the equivalent of dec_trivial
where the statement has metavariables? Mathport tells me it's decide
but it can't solve 0 < n + 1
where n
is a natural number since it has the metavariable n
.
Ruben Van de Velde (Jun 21 2023 at 20:04):
That looks like a variable, not a metavariable
Yury G. Kudryashov (Jun 21 2023 at 20:43):
I think that dec_trivial
in Lean 3 tried to start the decision procedure even if the goal had variables. It looks like in Lean 4 it doesn't.
Yury G. Kudryashov (Jun 21 2023 at 20:45):
So, you should use a lemma (e.g., docs4#Nat.succ_pos in this case) and add a porting note.
Kyle Miller (Jun 21 2023 at 21:01):
The word you're looking for is "free variable" by the way. The error that decide
gives is "expected type must not contain free or meta variables". A metavariable pretty prints as ?m
for some name m
.
When the issue is free variables, sometimes you can revert
all the variables that the goal depends on before doing decide
. That said, decide
doesn't seem like the right solution for this goal.
Yury G. Kudryashov (Jun 21 2023 at 21:12):
As far as I understand, in Lean 3 dec_trivial
tried to apply the algorithm from the decidable
instance and succeeded if the algorithm didn't need any structural information that is not available.
Yury G. Kudryashov (Jun 21 2023 at 21:12):
E.g., in this case we know that RHS is Nat.succ _
, so we can immediately say that 0 < n + 1
is true.
Kyle Miller (Jun 21 2023 at 21:26):
I tried turning off the check, and in this case it still can't decide that 0 < n + 1
is true.
open Lean Elab Term Meta Tactic
private def preprocessPropToDecide (expectedType : Expr) : TermElabM Expr := do
let mut expectedType ← instantiateMVars expectedType
if expectedType.hasFVar then
expectedType ← zetaReduce expectedType
return expectedType
elab "decide'" : tactic => do
closeMainGoalUsing fun expectedType => do
let expectedType ← preprocessPropToDecide expectedType
let d ← mkDecide expectedType
let d ← instantiateMVars d
let r ← withDefault <| whnf d
unless r.isConstOf ``true do
throwError "failed to reduce to 'true'{indentExpr r}"
let s := d.appArg! -- get instance from `d`
let rflPrf ← mkEqRefl (toExpr true)
return mkApp3 (Lean.mkConst ``of_decide_eq_true) expectedType s rflPrf
example (n : Nat) : 0 < n + 1 := by
decide'
/-
failed to reduce to 'true'
Decidable.rec (fun h ↦ (fun x ↦ false) h) (fun h ↦ (fun x ↦ true) h) (Nat.decLt 0 (n + 1))
-/
Kyle Miller (Jun 21 2023 at 21:28):
It seems like when it reduces the expression it's able to get Nat.rec (fun x ↦ true) (fun n n_ih x ↦ true) n PUnit.unit
, but it's not able to see that this is true independent of the value of n
.
David Ang (Jun 21 2023 at 21:28):
Yeah it's a free variable (my bad), but in my defense I did have a (more complicated) example that has a bunch of metavariables :P
Last updated: Dec 20 2023 at 11:08 UTC