Zulip Chat Archive

Stream: lean4

Topic: unknown identifier after it was introduced


Jireh Loreaux (Oct 11 2023 at 16:56):

Can someone explain why I'm getting this error in the last example? Clearly my metaprogramming skills are still horrendous.

import Std.Logic

open Lean Expr Meta

/-
Ensures that `goal` and `e` are proofs of some proposition.
If both have the form `∀ x : myType, _`, this should do, effectively, `refine forall_imp ?_ e`.
-/
def peelForall (goal : MVarId) (e : Expr) : MetaM (List MVarId) := do
  goal.withContext do
    let ty  whnfR ( inferType e)
    let target  whnfR ( goal.getType)
    -- check that everything is a `Prop`
    unless ( isProp ty) && ( isProp target) do
      dbg_trace s!"`peelForall` only works for propositions"
      return [goal]
    -- match `ty` and `target` as `∀` expressions.
    match ty, target with
      | .forallE n₁ t₁ b₁ c₁, .forallE _ t₂ b₂ _ => do
        dbg_trace s!"matched forall expressions"
        -- make sure they are quantified over the same type
        unless  isDefEq ( whnfR t₁) ( whnfR t₂) do
          dbg_trace s!"forall statements don't have the same type"
          return [goal]
        withLocalDecl n₁ c₁ t₁ fun x => do
          let type₁ := b₁.instantiate1 x
          let type₂ := b₂.instantiate1 x
          -- apply `forall_imp` and return the resulting goal list.
          let all_imp  mkFreshExprMVar ( mkForallFVars #[x] ( mkArrow type₁ type₂))
          goal.assign ( mkAppM ``forall_imp #[all_imp, e])
          return[all_imp.mvarId!]
      | _, _ => do
        -- if they aren't `forall` expressions, error.
        dbg_trace s!"couldn't match forall expressions"
        return [goal]

elab "peel" e:term : tactic => do
  let e  Elab.Term.elabTerm e none
  Elab.Tactic.liftMetaTactic (peelForall · e)

example (p q : Nat  Prop) (h :  y, p y) (h₁ :  z, p z  q z) :  x, q x := by
  peel h
  exact h₁
  done
  -- the above works as expected.

example (q : Nat  Prop) (r : Prop) (h : Nat  r) :  x, q x := by
  peel h
  -- success
  sorry
  done

example (p q : Nat  Nat  Prop) (h :  x y, p x y) (h₁ :  w z, p w z  q w z) :  i j, q i j := by
  refine forall_imp ?_ h
  intro n hp
  refine forall_imp ?_ hp
  -- this is what I expect to happen below, but it fails.
  sorry
  done
example (p q : Nat  Nat  Prop) (h :  x y, p x y) (h₁ :  w z, p w z  q w z) :  i j, q i j := by
  peel h
  intro n hp
  peel hp -- unknown identifier `hp`
  -- what did I do wrong?
  sorry
  done

Damiano Testa (Oct 11 2023 at 17:34):

I wonder if you should embrace that e should be an ident and go via getId and finding the corresponding LocalDecl. It seems that newly introduced decls are ignored, even with the withContext. Anyway, I can't properly debug this now, sorry!

Jireh Loreaux (Oct 11 2023 at 17:35):

Well, it would be nice to supply a term as well, not just something from the local context, which is why I was taking this approach.

Adam Topaz (Oct 11 2023 at 18:06):

It's a context issue again, I think:

elab "peel" e:term : tactic => Elab.Tactic.withMainContext do
  let e  Elab.Term.elabTerm e none
  Elab.Tactic.liftMetaTactic (peelForall · e)

Jireh Loreaux (Oct 11 2023 at 18:11):

Perfect, thanks!


Last updated: Dec 20 2023 at 11:08 UTC