lean4-htt/tests/elab/KyleAlg.lean
Kyle Miller 0db4ac18e5
feat: beta reduce while elaborating applications (#13807)
This PR modifies the app elaborator to beta reduce arguments while
substituting them into expected types for later arguments. This makes it
consistent with `inferType` and `instantiateMVars`, which both beta
reduce substitutions. In particular, this change ensures that the app
elaborator behaves as if it creates metavariables for each parameter and
assigns elaborated arguments to the metavariables. **Breaking change:**
tactic proofs may need to be modified to remove unnecessary steps, e.g.
`dsimp only` steps that were previously for beta reductions.
2026-05-21 07:26:00 +00:00

280 lines
8 KiB
Text
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import Lean
set_option warn.classDefReducibility false
/- from core:
class OfNat (α : Type u) (n : Nat) where
ofNat : α
class Mul (α : Type u) where
mul : ααα
class Add (α : Type u) where
add : ααα
-/
export One (one)
export Zero (zero)
class MulComm (α : Type u) [Mul α] : Prop where
mulComm : {a b : α} → a * b = b * a
export MulComm (mulComm)
class MulAssoc (α : Type u) [Mul α] : Prop where
mulAssoc : {a b c : α} → a * b * c = a * (b * c)
export MulAssoc (mulAssoc)
class OneUnit (α : Type u) [Mul α] [One α] : Prop where
oneMul : {a : α} → 1 * a = a
mulOne : {a : α} → a * 1 = a
export OneUnit (oneMul mulOne)
class AddComm (α : Type u) [Add α] : Prop where
addComm : {a b : α} → a + b = b + a
export AddComm (addComm)
class AddAssoc (α : Type u) [Add α] : Prop where
addAssoc : {a b c : α} → a + b + c = a + (b + c)
export AddAssoc (addAssoc)
class ZeroUnit (α : Type u) [Add α] [Zero α] : Prop where
zeroAdd : {a : α} → 0 + a = a
addZero : {a : α} → a + 0 = a
export ZeroUnit (zeroAdd addZero)
class InvMul (α : Type u) [Mul α] [One α] [Inv α] : Prop where
invMul : {a : α} → a⁻¹ * a = 1
export InvMul (invMul)
class NegAdd (α : Type u) [Add α] [Zero α] [Neg α] : Prop where
negAdd : {a : α} → -a + a = 0
export NegAdd (negAdd)
class ZeroMul (α : Type u) [Mul α] [Zero α] : Prop where
zeroMul : {a : α} → 0 * a = 0
export ZeroMul (zeroMul)
class Distrib (α : Type u) [Add α] [Mul α] : Prop where
leftDistrib : {a b c : α} → a * (b + c) = a * b + a * c
rightDistrib : {a b c : α} → (a + b) * c = a * c + b * c
export Distrib (leftDistrib rightDistrib)
class Domain (α : Type u) [Mul α] [Zero α] : Prop where
eqZeroOrEqZeroOfMulEqZero : {a b : α} → a * b = 0 → a = 0 b = 0
export Domain (eqZeroOrEqZeroOfMulEqZero)
class Semigroup (α : Type u) extends Mul α, MulAssoc α
attribute [instance] Semigroup.mk
class AddSemigroup (α : Type u) extends Add α, AddAssoc α
attribute [instance] AddSemigroup.mk
class Monoid (α : Type u) extends Semigroup α, One α, OneUnit α
attribute [instance] Monoid.mk
class AddMonoid (α : Type u) extends AddSemigroup α, Zero α, ZeroUnit α
attribute [instance] AddMonoid.mk
class CommSemigroup (α : Type u) extends Semigroup α, MulComm α
attribute [instance] CommSemigroup.mk
class CommMonoid (α : Type u) extends Monoid α, MulComm α
attribute [instance] CommMonoid.mk
class Group (α : Type u) extends Monoid α, Inv α, InvMul α
attribute [instance] Group.mk
class AddGroup (α : Type u) extends AddMonoid α, Neg α, NegAdd α
attribute [instance] AddGroup.mk
class Semiring (α : Type u) extends AddMonoid α, Monoid α, AddComm α, ZeroMul α, Distrib α
attribute [instance] Semiring.mk
class Ring (α : Type u) extends AddGroup α, Monoid α, AddComm α, Distrib α
attribute [instance] Ring.mk
class CommRing (α : Type u) extends Ring α, MulComm α
attribute [instance] CommRing.mk
class IntegralDomain (α : Type u) extends CommRing α, Domain α
attribute [instance] IntegralDomain.mk
section test1
variable (α : Type u) [h : CommMonoid α]
example : Semigroup α := inferInstance
example : Monoid α := inferInstance
example : CommSemigroup α := inferInstance
end test1
section test2
variable (β : Type u) [CommSemigroup β] [One β] [OneUnit β]
example : Monoid β := inferInstance
example : CommMonoid β := inferInstance
example : Semigroup β := inferInstance
end test2
section test3
variable (β : Type u) [Mul β] [One β] [MulAssoc β] [OneUnit β]
example : Monoid β := inferInstance
example : Semigroup β := inferInstance
end test3
theorem negZero [AddGroup α] : -(0 : α) = 0 := by
rw [←addZero (a := -(0 : α)), negAdd]
theorem subZero [AddGroup α] {a : α} : a + -(0 : α) = a := by
rw [←addZero (a := a), addAssoc, negZero, addZero]
theorem negNeg [AddGroup α] {a : α} : -(-a) = a := by {
rw [←addZero (a := - -a)];
rw [←negAdd (a := a)];
rw [←addAssoc];
rw [negAdd];
rw [zeroAdd];
}
theorem addNeg [AddGroup α] {a : α} : a + -a = 0 := by {
have h : - -a + -a = 0 := by { rw [negAdd] };
rw [negNeg] at h;
exact h
}
theorem addIdemIffZero [AddGroup α] {a : α} : a + a = a ↔ a = 0 := by
apply Iff.intro
focus
intro h
have h' := congrArg (λ x => x + -a) h
rw [addAssoc, addNeg, addZero] at h'
exact h'
focus
intro h
subst a
rw [addZero]
instance [Ring α] : ZeroMul α := by {
apply ZeroMul.mk;
intro a;
have h : 0 * a + 0 * a = 0 * a := by { rw [←rightDistrib, addZero] };
rw [addIdemIffZero (a := 0 * a)] at h;
rw [h];
}
example [Ring α] : Semiring α := inferInstance
section prod
instance [Mul α] [Mul β] : Mul (α × β) where
mul p p' := (p.1 * p'.1, p.2 * p'.2)
instance [Inv α] [Inv β] : Inv (α × β) where
inv p := (p.1⁻¹, p.2⁻¹)
instance [One α] [One β] : One (α × β) where
one := (1, 1)
theorem Product.ext : {p q : α × β} → p.1 = q.1 → p.2 = q.2 → p = q
| (a, b), (c, d) => by simp_all
instance [Semigroup α] [Semigroup β] : Semigroup (α × β) where
mulAssoc := by
intros
apply Product.ext
apply mulAssoc
apply mulAssoc
instance [Monoid α] [Monoid β] : Monoid (α × β) where
oneMul := by
intros
apply Product.ext
apply oneMul
apply oneMul
mulOne := by
intros
apply Product.ext
apply mulOne
apply mulOne
instance [Group α] [Group β] : Group (α × β) where
invMul := by
intros
apply Product.ext
apply invMul
apply invMul
end prod
def test1 {G : Type _} [Group G]: Group (G) := inferInstance
def test2 {G : Type _} [Group G]: Group (G × G) := inferInstance
def test3 {G : Type _} [Group G]: Group (G × G × G) := inferInstance
def test4 {G : Type _} [Group G]: Group (G × G × G × G) := inferInstance
def test5 {G : Type _} [Group G]: Group (G × G × G × G × G) := inferInstance
def test6 {G : Type _} [Group G]: Group (G × G × G × G × G × G) := inferInstance
def test7 {G : Type _} [Group G]: Group (G × G × G × G × G × G × G) := inferInstance
def test8 {G : Type _} [Group G]: Group (G × G × G × G × G × G × G × G) := inferInstance
namespace Lean
unsafe def Expr.dagSizeUnsafe (e : Expr) : IO Nat := do
let (_, s) ← visit e |>.run ({}, 0)
return s.2
where
visit (e : Expr) : StateRefT (Std.HashSet USize × Nat) IO Unit := do
let addr := ptrAddrUnsafe e
unless (← get).1.contains addr do
modify fun (s, c) => (s.insert addr, c+1)
match e with
| Expr.proj _ _ s => visit s
| Expr.forallE _ d b _ => visit d; visit b
| Expr.lam _ d b _ => visit d; visit b
| Expr.letE _ t v b _ => visit t; visit v; visit b
| Expr.app f a => visit f; visit a
| Expr.mdata _ b => visit b
| _ => return ()
@[implemented_by Expr.dagSizeUnsafe]
opaque Expr.dagSize (e : Expr) : IO Nat
def getDeclTypeValueDagSize (declName : Name) : CoreM Nat := do
let info ← getConstInfo declName
let n ← info.type.dagSize
match info.value? with
| none => return n
| some v => return n + (← v.dagSize)
#eval getDeclTypeValueDagSize `test2
#eval getDeclTypeValueDagSize `test3
#eval getDeclTypeValueDagSize `test4
#eval getDeclTypeValueDagSize `test5
#eval getDeclTypeValueDagSize `test6
#eval getDeclTypeValueDagSize `test7
#eval getDeclTypeValueDagSize `test8
def reduceAndGetDagSize (declName : Name) : MetaM Nat := do
let c := mkConst declName [Level.one]
let e ← Meta.reduce c
trace[Meta.debug] "{e}"
e.dagSize
#eval reduceAndGetDagSize `test1
#eval reduceAndGetDagSize `test2
#eval reduceAndGetDagSize `test3
#eval reduceAndGetDagSize `test4
#eval reduceAndGetDagSize `test5
#eval reduceAndGetDagSize `test6
#eval reduceAndGetDagSize `test7
-- Use `set_option` to trace the reduced term
set_option pp.all true in
set_option trace.Meta.debug true in
#eval reduceAndGetDagSize `test8