feat: allow relations in Type at Trans

It addresses issue reported at https://leanprover.zulipchat.com/#narrow/stream/270676-lean4/topic/Calc.20mode/near/291214574
This commit is contained in:
Leonardo de Moura 2022-07-28 10:13:01 -07:00
parent d0d5effcbc
commit ee6e2036dd
3 changed files with 31 additions and 7 deletions

View file

@ -451,15 +451,15 @@ class LT (α : Type u) where lt : αα → Prop
ite (LE.le a b) a b
/-- Transitive chaining of proofs, used e.g. by `calc`. -/
class Trans (r : α → β → Prop) (s : β → γ → Prop) (t : outParam (αγ → Prop)) where
class Trans (r : α → β → Sort u) (s : β → γ → Sort v) (t : outParam (αγ → Sort w)) where
trans : r a b → s b c → t a c
export Trans (trans)
instance (r : αγProp) : Trans Eq r r where
instance (r : αγSort u) : Trans Eq r r where
trans heq h' := heq ▸ h'
instance (r : α → β → Prop) : Trans r Eq r where
instance (r : α → β → Sort u) : Trans r Eq r where
trans h' heq := heq ▸ h'
class HAdd (α : Type u) (β : Type v) (γ : outParam (Type w)) where

View file

@ -18,16 +18,25 @@ def getCalcRelation? (e : Expr) : MetaM (Option (Expr × Expr × Expr)) :=
else
return some (e.appFn!.appFn!, e.appFn!.appArg!, e.appArg!)
private def getRelUniv (r : Expr) : MetaM Level := do
let rType ← inferType r
forallTelescopeReducing rType fun _ sort => do
let .sort u ← whnf sort | throwError "unexpected relation type{indentExpr rType}"
return u
def mkCalcTrans (result resultType step stepType : Expr) : MetaM (Expr × Expr) := do
let some (r, a, b) ← getCalcRelation? resultType | unreachable!
let some (s, _, c) ← getCalcRelation? (← instantiateMVars stepType) | unreachable!
let u ← getRelUniv r
let v ← getRelUniv s
let (α, β, γ) := (← inferType a, ← inferType b, ← inferType c)
let (u_1, u_2, u_3) := (← getLevel α, ← getLevel β, ← getLevel γ)
let t ← mkFreshExprMVar (← mkArrow α (← mkArrow γ (mkSort levelZero)))
let selfType := mkAppN (Lean.mkConst ``Trans [u_1, u_2, u_3]) #[α, β, γ, r, s, t]
let w ← mkFreshLevelMVar
let t ← mkFreshExprMVar (← mkArrow α (← mkArrow γ (mkSort w)))
let selfType := mkAppN (Lean.mkConst ``Trans [u, v, w, u_1, u_2, u_3]) #[α, β, γ, r, s, t]
match (← trySynthInstance selfType) with
| LOption.some self =>
let result := mkAppN (Lean.mkConst ``Trans.trans [u_1, u_2, u_3]) #[α, β, γ, r, s, t, self, a, b, c, result, step]
| .some self =>
let result := mkAppN (Lean.mkConst ``Trans.trans [u, v, w, u_1, u_2, u_3]) #[α, β, γ, r, s, t, self, a, b, c, result, step]
let resultType := (← instantiateMVars (← inferType result)).headBeta
unless (← getCalcRelation? resultType).isSome do
throwError "invalid 'calc' step, step result is not a relation{indentExpr resultType}"

View file

@ -0,0 +1,15 @@
inductive EQ {α : Type} (a : α) : α → Type where
| refl : EQ a a
def EQ.trans (h₁ : EQ a b) (h₂ : EQ b c) : EQ a c := by
cases h₁; cases h₂; constructor
instance : Trans (@EQ α) (@EQ α) (@EQ α) where
trans := EQ.trans
infix:50 " ≋ " => EQ
example (h₁ : EQ a b) (h₂ : b = c) (h₃ : EQ c d) : EQ a d := by
calc a ≋ b := h₁
_ = c := h₂
_ ≋ d := h₃