-
Notifications
You must be signed in to change notification settings - Fork 717
Open
Labels
P-mediumWe may work on this issue if we find the timeWe may work on this issue if we find the time
Description
Consider this attempt at pattern matching on a redex in an intrinsically typed lambda calculus:
inductive Ty where
| unit : Ty
| arrow (t₁ t₂ : Ty) : Ty
def Env (n : Nat) := Fin n → Ty
@[reducible] def Env.add (Γ : Env n) (t : Ty) : Env (n + 1) :=
Fin.cases t Γ
inductive Term : Env n → Ty → Type where
| var (i : Fin n) : Term Γ (Γ i)
| app (e₁ : Term Γ (.arrow t₁ t₂)) (e₂ : Term Γ t₁) : Term Γ t₂
| lam (e : Term (Γ.add t₁) t₂) : Term Γ (.arrow t₁ t₂)
axiom Term.subst : Term (Γ.add t₁) t₂ → Term Γ t₁ → Term Γ t₂
/--
error: Tactic `cases` failed with a nested error:
Dependent elimination failed: Failed to solve equation
t₁✝.arrow t✝ = Γ i✝
at case `var` after processing
_, (app _ _ _ _ _ _)
the dependent pattern matcher can solve the following kinds of equations
- <var> = <term> and <term> = <var>
- <term> = <term> where the terms are definitionally equal
- <constructor> = <constructor>, examples: List.cons x xs = List.cons y ys, and List.cons x xs = List.nil
-/
#guard_msgs in
def Term.step : (e : Term Γ t) → Option (Term Γ t)
| .var i => none
| .app (.lam e₁) e₂ => some (e₁.subst e₂)
| .app _ _ => none
| .lam e => none
-- Minimized
/--
error: Tactic `cases` failed with a nested error:
Dependent elimination failed: Failed to solve equation
t₁.arrow t₂ = Γ i✝
at case `Term.var` after processing
_
the dependent pattern matcher can solve the following kinds of equations
- <var> = <term> and <term> = <var>
- <term> = <term> where the terms are definitionally equal
- <constructor> = <constructor>, examples: List.cons x xs = List.cons y ys, and List.cons x xs = List.nil
-/
#guard_msgs in
def getLamBody? : Term Γ (.arrow t₁ t₂) → Option (Term (Γ.add t₁) t₂)
| .lam e' => some e'
| _ => none
-- Workaround 1: Manual generalization
def getLamBody?' : Term Γ (.arrow t₁ t₂) → Option (Term (Γ.add t₁) t₂) := aux rfl
where
aux {t} : (t = Ty.arrow t₁ t₂) → Term Γ t → Option (Term (Γ.add t₁) t₂)
| h, .lam e' => Ty.noConfusion h fun h₁ h₂ => some (h₁ ▸ h₂ ▸ e')
| _, _ => none
-- Non-Workaround 2: Boolean predicate (did not actually work)
@[reducible] def isLam : Term Γ t → Bool
| .lam _ => true
| _ => false
def getLamBody : (e : Term Γ (.arrow t₁ t₂)) → isLam e → Term (Γ.add t₁) t₂
| .lam e, rfl => e
This during match compilation in the inner match, see the more minimal example getLamBody?.
It is a workaround to manually generalize the index. I was hoping that adding a reducible predicate that asserts we are in the case would help, but it doesn't.
I wonder if this should work: The pattern does not mention .var, so why is it trying to solve for it.
I’ll wager (but didn't check yet) that using sparse casesOn (#10823) might fix this issue – but accidentialy so, or for good reasons?
Also, should the “discriminant refinement procedure” auto-generalize the indices here, or is that out of scope?
Version
Lean 4.25.0-nightly-2025-10-21
Metadata
Metadata
Assignees
Labels
P-mediumWe may work on this issue if we find the timeWe may work on this issue if we find the time