Tutorial Test Cases
These are the test cases from the Lean Kernel Arena tutorial. Each test is a small Lean 4 environment exported via lean4export. Good tests (👍) should be accepted by a correct kernel implementation; bad tests (✋) should be rejected. Later tests build on declarations from earlier ones; shared declarations are listed under Includes.
👍 001_basicDef
Basic definition
def basicDef : Type := Prop
✋ 002_badDef
Mismatched types
def badDef : Prop := Type
👍 003_arrowType
Arrow type (function type)
def arrowType : Type := Prop → Prop
👍 004_dependentType
Dependent type (forall)
def dependentType : Prop := ∀ (p : Prop), p
👍 005_constType
Lambda expression
def constType : Type → Type → Type := fun (x y : Type) => x
👍 006_betaReduction
Lambda reduction
def betaReduction : constType Prop (Prop → Prop) := ∀ (p : Prop), p
👍 007_betaReduction2
Lambda reduction under binder
def betaReduction2 : (p : Prop) → constType Prop (Prop → Prop) := fun (p : Prop) => p
👍 008_forallSortWhnf
The binding domain of a forall may need to be reduce before it is a sort
def id.{u} : {α : Sort u} → (a : α) → α := fun {α : Sort u} (a : α) => a def forallSortWhnf : Prop := ∀ (p : @id.{2} Type Prop) (a : p), p
✋ 009_forallSortBad
The binding domain of a forall has to be a sort
def forallSortBad : Prop := (x : @id.{2} Type Prop) → (x : x) → (a : x) → x
✋ 010_nonTypeType
The type of a declaration has to be a type, not some other expression
def nonTypeType : constType := Prop
✋ 011_nonTypeAxiom
This applies to axioms as well, which are easy to overlook because they have no value to check the type against. Letting one through is not merely untidy: an axiom whose type is an arbitrary term inhabits whatever that term is later found definitionally equal to, and the eta and proof irrelevance rules are happy to equate a term like this with a great many things.
axiom nonTypeAxiom : constType
✋ 012_nonPropThm
The type of a theorem has to be a proposition
theorem nonPropThm : Prop := ∀ (x : Prop), x
👍 013_levelComp1
Some level computation
def levelComp1 : Type := Sort (imax 1 0)
👍 014_levelComp2
Some level computation
def levelComp2 : Type 1 := Sort (imax 0 1)
👍 015_levelComp3
Some level computation
def levelComp3 : Type 2 := Type (max 1 0)
👍 016_levelParams
Level parameters
def levelParamF.{u} : Sort u → Sort u → Sort u := fun (α β : Sort u) => α def levelParams : levelParamF.{1} Prop (Prop → Prop) := ∀ (p : Prop), p
✋ 017_tut06_bad01
Duplicate universe parameters
def tut06_bad01.{u, u} : Type := Prop
👍 018_levelComp4
Some level computation
def levelComp4.{u} : Type := Prop
👍 019_levelComp5
Some level computation
def levelComp5.{u} : Type u := Sort u
👍 020_imax1
Type inference for forall using imax
def imax1 : (p : Prop) → Prop := fun (p : Prop) => ∀ (a : Type), p
👍 021_imax2
Type inference for forall using imax
def imax2 : (α : Type) → Type 1 := fun (α : Type) => Type → α
👍 022_levelMaxComm
Level equality: max is commutative (max u v ≈ max v u).
def levelMaxComm.{u, v} : Type (max v u) := Sort (max u v)
👍 023_levelMaxAssoc
Level equality: max is associative (max (max u v) w ≈ max u (max v w)).
def levelMaxAssoc.{u, v, w} : Type (max u v w) := Sort (max (max u v) w)
👍 024_levelMaxIdem
Level equality: max is idempotent (max u u ≈ u).
def levelMaxIdem.{u} : Type u := Sort (max u u)
👍 025_levelMaxAbsorb
Level equality: max absorption (max u (max u v) ≈ max u v).
def levelMaxAbsorb.{u, v} : Type (max u v) := Sort (max u u v)
👍 026_inferVar
Type inference of local variables
def inferVar : ∀ (f : Prop) (g : f), f := fun (f : Prop) (g : f) => g
👍 027_defEqLambda
Definitional equality between lambdas
def defEqLambda : ∀ (f : (Prop → Prop) → Prop) (g : ∀ (a : Prop → Prop), f a), f fun (p : Prop) => p → p := fun (f : (Prop → Prop) → Prop) (g : ∀ (a : Prop → Prop), f a) => g fun (p : Prop) => p → p
👍 028_peano1
Peano arithmetic: 2 = 2
def PN.{u_1} : Sort (imax (u_1 + 1) u_1) := (α : Sort u_1) → (α → α) → α → α def PN.succ.{u_1} : PN.{u_1} → PN.{u_1} := fun (n : PN.{u_1}) (α : Sort u_1) (s : α → α) (z : α) => s (n α s z) def PN.zero.{u_1} : PN.{u_1} := fun (α : Sort u_1) (s : α → α) (z : α) => z def PN.lit0.{u_1} : PN.{u_1} := PN.zero.{u_1} def PN.lit1.{u_1} : PN.{u_1} := PN.succ.{u_1} PN.lit0.{u_1} def PN.lit2.{u_1} : PN.{u_1} := PN.succ.{u_1} PN.lit1.{u_1} theorem peano1.{u} : ∀ (t : PN.{u} → Prop) (v : ∀ (n : PN.{u}), t n), t PN.lit2.{u} := fun (t : PN.{u} → Prop) (v : ∀ (n : PN.{u}), t n) => v PN.lit2.{u}
👍 029_peano2
Peano arithmetic: 1 + 1 = 2
def PN.add.{u_1} : PN.{u_1} → PN.{u_1} → PN.{u_1} := fun (n m : PN.{u_1}) (α : Sort u_1) (s : α → α) (z : α) => n α s (m α s z) theorem peano2.{u} : ∀ (t : PN.{u} → Prop) (v : ∀ (n : PN.{u}), t n), t PN.lit2.{u} := fun (t : PN.{u} → Prop) (v : ∀ (n : PN.{u}), t n) => v (PN.add.{u} PN.lit1.{u} PN.lit1.{u})
👍 030_peano3
Peano arithmetic: 2 * 2 = 4
def PN.lit3.{u_1} : PN.{u_1} := PN.succ.{u_1} PN.lit2.{u_1} def PN.lit4.{u_1} : PN.{u_1} := PN.succ.{u_1} PN.lit3.{u_1} def PN.mul.{u_1} : PN.{u_1} → PN.{u_1} → PN.{u_1} := fun (n m : PN.{u_1}) (α : Sort u_1) (s : α → α) (z : α) => n α (m α s) z theorem peano3.{u} : ∀ (t : PN.{u} → Prop) (v : ∀ (n : PN.{u}), t n), t PN.lit4.{u} := fun (t : PN.{u} → Prop) (v : ∀ (n : PN.{u}), t n) => v (PN.mul.{u} PN.lit2.{u} PN.lit2.{u})
👍 031_letType
Type checking a non-dependent let
def letType : Type := let x : Type := Prop; x
👍 032_letTypeDep
Type checking a dependent let
axiom aDepProp : Type → Prop axiom mkADepProp : ∀ (t : Type), aDepProp t def letTypeDep : aDepProp Prop := let x : Type := Prop; mkADepProp x
👍 033_letRed
Reducing a let
axiom aProp : Prop def letRed : let x : Type := Prop; x := aProp
👍 034_empty
A simple empty inductive type
inductive Empty : Type def empty : Type := Empty
👍 035_boolType
A simple enumeration inductive type
👍 036_twoBool
A simple product type
👍 037_andType
A parametrized product type (no level parameters)
👍 038_prodType
A parametrized product type (with level parameters)
inductive Prod.{u, v} (α : Type u) (β : Type v) : Type (max u v) constructor Prod.mk.{u, v} : {α : Type u} → {β : Type v} → (fst : α) → (snd : β) → Prod.{u, v} α β def prodType : Type → Type → Type := Prod.{0, 0}
👍 039_pprodType
A parametrized product type (with more general level parameters)
inductive PProd.{u, v} (α : Sort u) (β : Sort v) : Sort (max (max 1 u) v) constructor PProd.mk.{u, v} : {α : Sort u} → {β : Sort v} → (fst : α) → (snd : β) → PProd.{u, v} α β def pprodType : Type → Type → Type := PProd.{1, 1}
👍 040_pUnitType
Level-polymorphic unit type
👍 041_eqType
Equality, as an important indexed non-recursive data type
👍 042_natDef
A recursive inductive data type
👍 043_rbTreeDef
A recursive indexed data type
inductive Color : Type constructor Color.r : Color constructor Color.b : Color inductive RBTree.{u} (α : Type u) : Color → N → Type u constructor RBTree.leaf.{u} : {α : Type u} → RBTree.{u} α Color.b N.zero constructor RBTree.red.{u} : {α : Type u} → {n : N} → RBTree.{u} α Color.b n → α → RBTree.{u} α Color.b n → RBTree.{u} α Color.r n constructor RBTree.black.{u} : {α : Type u} → {c1 c2 : Color} → {n : N} → RBTree.{u} α c1 n → α → RBTree.{u} α c2 n → RBTree.{u} α Color.b (N.succ n) def rbTreeDef.{u} : (α : Type u) → Color → N → Type u := RBTree.{u}
✋ 044_inductBadNonSort
An inductive type with a non-sort type
inductive inductBadNonSort : constType
✋ 045_inductBadNonSort2
Another inductive type with a non-sort type
axiom aType : Type inductive inductBadNonSort2 : aType
✋ 046_inductLevelParam
An inductive with duplicate level params
inductive inductLevelParam.{u, u} : Type
✋ 047_inductTooFewParams
An inductive with too few parameters in the type
inductive inductTooFewParams (x : Prop) : Prop
✋ 048_inductWrongCtorParams
An inductive with a constructor with wrong parameters
inductive inductWrongCtorParams (x : Prop) : Type constructor inductWrongCtorParams.mk : (x : Type) → inductWrongCtorParams aProp
✋ 049_inductWrongCtorResParams
An inductive with a constructor with wrong parameters in result (they are swapped)
inductive inductWrongCtorResParams (x : Prop) (y : Prop) : Type constructor inductWrongCtorResParams.mk : (x y : Prop) → inductWrongCtorResParams y x
✋ 050_inductWrongCtorResLevel
An inductive with a constructor with wrong level parameters in result (they are swapped)
inductive inductWrongCtorResLevel.{u1, u2} (x : Prop) (y : Prop) : Type constructor inductWrongCtorResLevel.mk.{u1, u2} : (x y : Prop) → inductWrongCtorResLevel.{u2, u1} x y
✋ 051_inductInIndex
A constructor with an unexpected occurrence of the type in index position of a return type.
inductive inductInIndex : (x : Prop) → Prop constructor inductInIndex.mk : inductInIndex (inductInIndex aProp)
✋ 052_indNeg
The classic example of an inductive with negative recursive occurrence
👍 053_reduceCtorParam.mk
When checking inductives, we expect the kernel to reduce the types of constructor arguments.
inductive reduceCtorParam (a._@._internal._hyg.0 : Type) : Type constructor reduceCtorParam.mk : (α : @id.{3} (Type 1) Type) → (x : constType (reduceCtorParam α) (reduceCtorParam α)) → reduceCtorParam α
✋ 054_reduceCtorType.mk
When checking inductives, we expect the kernel to not reduce the type of the constructor itself;
that should be all manifest foralls
inductive reduceCtorType : Type constructor reduceCtorType.mk : @id.{2} Type reduceCtorType
✋ 055_indNegReducible
When checking inductives, we expect the kernel to not reduce the type of the constructor parameters further than head normal form. Recursive occurrences nested inside the head normal form are considered negative occurrences, even if they could be reduced to disappear.
inductive indNegReducible : Type constructor indNegReducible.mk : (x : (x : constType aType indNegReducible) → indNegReducible) → indNegReducible
👍 056_predWithTypeField
An inductive proposition can have constructors with fields of arbitrary level.
inductive PredWithTypeField : Prop constructor PredWithTypeField.mk : ∀ (α : Type), PredWithTypeField def predWithTypeField : Prop := PredWithTypeField
👍 057_typeWithTypeField
An inductive type can have fields of level up to that of the inductive.
inductive TypeWithTypeField : Type 1 constructor TypeWithTypeField.mk : (α : Type) → TypeWithTypeField def typeWithTypeField : Type 1 := TypeWithTypeField
👍 058_typeWithTypeFieldPoly
An inductive type can have fields of level up to that of the inductive (polymorphic variant).
inductive TypeWithTypeFieldPoly.{u} : Type (u + 1) constructor TypeWithTypeFieldPoly.mk.{u} : (α : Type u) → TypeWithTypeFieldPoly.{u} def typeWithTypeFieldPoly.{u} : Type (u + 1) := TypeWithTypeFieldPoly.{u}
✋ 059_typeWithTooHighTypeField.mk
An inductive type can have fields of from higher universes.
inductive typeWithTooHighTypeField : Type constructor typeWithTooHighTypeField.mk : (x : Type) → typeWithTooHighTypeField
👍 060_emptyRec
Asserting the type of the generated recursor
def emptyRec.{u} : (motive : (t : Empty) → Sort u) → (t : Empty) → motive t := Empty.rec.{u}
👍 061_boolRec
Asserting the type of the generated recursor
def boolRec.{u} : {motive : (t : Bool) → Sort u} → (false : motive Bool.false) → (true : motive Bool.true) → (t : Bool) → motive t := fun {motive : (t : Bool) → Sort u} (false : motive Bool.false) (true : motive Bool.true) (t : Bool) => @Bool.rec.{u} motive false true t
👍 062_twoBoolRec
Asserting the type of the generated recursor
def twoBoolRec.{u} : {motive : (t : TwoBool) → Sort u} → (mk : (b1 b2 : Bool) → motive (TwoBool.mk b1 b2)) → (t : TwoBool) → motive t := fun {motive : (t : TwoBool) → Sort u} (mk : (b1 b2 : Bool) → motive (TwoBool.mk b1 b2)) (t : TwoBool) => @TwoBool.rec.{u} motive mk t
👍 063_andRec
Asserting the type of the generated recursor
def andRec.{u} : {a b : Prop} → {motive : (t : And a b) → Sort u} → (intro : (left : a) → (right : b) → motive (@And.intro a b left right)) → (t : And a b) → motive t := @And.rec.{u}
👍 064_prodRec
Asserting the type of the generated recursor
def prodRec.{u, v, w} : (α : Type u) → (β : Type v) → {motive : Prod.{u, v} α β → Sort u} → (mk : (fst : α) → (snd : β) → motive (@Prod.mk.{u, v} α β fst snd)) → (t : Prod.{u, v} α β) → motive t := @Prod.rec.{u, u, v}
👍 065_pprodRec
Asserting the type of the generated recursor
def pprodRec.{u, v, w} : (α : Sort u) → (β : Sort v) → {motive : PProd.{u, v} α β → Sort u} → (mk : (fst : α) → (snd : β) → motive (@PProd.mk.{u, v} α β fst snd)) → (t : PProd.{u, v} α β) → motive t := @PProd.rec.{u, u, v}
👍 066_punitRec
Asserting the type of the generated recursor
def punitRec.{u, w} : {motive : PUnit.{u} → Sort w} → (unit : motive PUnit.unit.{u}) → (t : PUnit.{u}) → motive t := @PUnit.rec.{w, u}
👍 067_eqRec
Asserting the type of the generated recursor
def eqRec.{u, u_1} : {α : Sort u_1} → {a : α} → {motive : (a_1 : α) → (t : @Eq.{u_1} α a a_1) → Sort u} → (refl : motive a (@Eq.refl.{u_1} α a)) → {a_1 : α} → (t : @Eq.{u_1} α a a_1) → motive a_1 t := @Eq.rec.{u, u_1}
👍 068_nRec
Asserting the type of the generated recursor
👍 069_rbTreeRef
Asserting the type of the generated recursor
def rbTreeRef.{u} : {α : Type u} → {motive : (a : Color) → (a_1 : N) → RBTree.{u} α a a_1 → Sort u} → (leaf : motive Color.b N.zero (@RBTree.leaf.{u} α)) → (red : {n : N} → (a : RBTree.{u} α Color.b n) → (a_1 : α) → (a_2 : RBTree.{u} α Color.b n) → motive Color.b n a → motive Color.b n a_2 → motive Color.r n (@RBTree.red.{u} α n a a_1 a_2)) → (black : {c1 c2 : Color} → {n : N} → (a : RBTree.{u} α c1 n) → (a_1 : α) → (a_2 : RBTree.{u} α c2 n) → motive c1 n a → motive c2 n a_2 → motive Color.b (N.succ n) (@RBTree.black.{u} α c1 c2 n a a_1 a_2)) → {a : Color} → {a_1 : N} → (t : RBTree.{u} α a a_1) → motive a a_1 t := @RBTree.rec.{u, u}
👍 070_boolPropRec
Inductive predicates eliminate into Prop if they have more than one constructor.
inductive BoolProp : Prop constructor BoolProp.a : BoolProp constructor BoolProp.b : BoolProp def boolPropRec : ∀ {motive : (t : BoolProp) → Prop} (a : motive BoolProp.a) (b : motive BoolProp.b) (t : BoolProp), motive t := @BoolProp.rec
✋ 071_BogusRecursor
A kernel must not blindly trust the recursors it is handed. If we write
inductive BogusRecursor : Type where
| mk : BogusRecursor
then the recursor BogusRecursor.rec will be correctly derived with type
{motive : BogusRecursor → Sort u} → motive .mk → (t : BogusRecursor) → motive t.
This test instead claims that the recursor is a constant of type False, and
then uses it to prove bogusRecursorFalse : False. A kernel that validates
the recursors it is handed rejects the bogus recursor itself; a kernel that
ignores them and derives the recursors anew rejects the proof of False
(the derived recursor neither has type False nor zero universe parameters).
Either way, this test must be rejected.
inductive False : Prop inductive BogusRecursor : Type constructor BogusRecursor.mk : BogusRecursor theorem bogusRecursorFalse : False := BogusRecursor.rec
👍 072_existsRec
Inductive predicates eliminate into Prop if they have one constructors and it carries data.
inductive Exists.{u} {α : Sort u} (p : α → Prop) : Prop constructor Exists.intro.{u} : ∀ {α : Sort u} {p : α → Prop} (w : α) (h : p w), @Exists.{u} α p def existsRec.{u} : ∀ {α : Sort u} {p : α → Prop} {motive : (t : @Exists.{u} α p) → Prop} (intro : ∀ (w : α) (h : p w), motive (@Exists.intro.{u} α p w h)) (t : @Exists.{u} α p), motive t := @Exists.rec.{u}
👍 073_typeSingletonRecReduction
Because NewSingleton is a singleton, NewSingleton.rec true x reduces to
true even though x is a variable.
inductive NewSingleton : Type constructor NewSingleton.mk : NewSingleton def rfl.{u} : ∀ {α : Sort u} {a : α}, @Eq.{u} α a a := fun {α : Sort u} {a : α} => @Eq.refl.{u} α a def typeSingletonRecReduction : ∀ (x : NewSingleton), @Eq.{1} Bool (@NewSingleton.rec.{1} (fun (x : NewSingleton) => Bool) Bool.true x) Bool.true := fun (x : NewSingleton) => @rfl.{1} Bool (@NewSingleton.rec.{1} (fun (x : NewSingleton) => Bool) Bool.true x)
👍 074_sortElimPropRec
Inductive predicates eliminate into Sort if they have one constructors and it carries data, but the data is known from the type, e.g. a parameter or an index
inductive SortElimProp (b : Bool) : Bool → Bool → Prop constructor SortElimProp.mk : ∀ {b : Bool} (b1 b2 : Bool), SortElimProp b b2 b1 def sortElimPropRec.{u} : {b : Bool} → {motive : (a a_1 : Bool) → (t : SortElimProp b a a_1) → Sort u} → (mk : (b1 b2 : Bool) → motive b2 b1 (@SortElimProp.mk b b1 b2)) → {a a_1 : Bool} → (t : SortElimProp b a a_1) → motive a a_1 t := @SortElimProp.rec.{u}
👍 075_sortElimProp2Rec
Inductive predicates eliminate into Sort if they have one constructors and it carries data, but the data is known from the type, e.g. a parameter or an index. However, it must occur directly in the result type, with no intervening reduction.
inductive SortElimProp2 (b : Bool) : Bool → Bool → Prop constructor SortElimProp2.mk : ∀ {b : Bool} (b1 b2 : Bool), SortElimProp2 b b2 (@id.{1} Bool b1) def sortElimProp2Rec : ∀ {b : Bool} {motive : (a a_1 : Bool) → (t : SortElimProp2 b a a_1) → Prop} (mk : ∀ (b1 b2 : Bool), motive b2 b1 (@SortElimProp2.mk b b1 b2)) {a a_1 : Bool} (t : SortElimProp2 b a a_1), motive a a_1 t := @SortElimProp2.rec
👍 076_boolRecEqns
Reduction behavior of Bool.rec
theorem boolRecEqns.{u} : And (∀ {motive : (t : Bool) → Sort u} (falseVal : motive Bool.false) (trueVal : motive Bool.true), @Eq.{u} (motive Bool.false) (@Bool.rec.{u} (fun (x : Bool) => motive x) falseVal trueVal Bool.false) falseVal) (∀ {motive : (t : Bool) → Sort u} (falseVal : motive Bool.false) (trueVal : motive Bool.true), @Eq.{u} (motive Bool.true) (@Bool.rec.{u} (fun (x : Bool) => motive x) falseVal trueVal Bool.true) trueVal) := @And.intro (∀ {motive : (t : Bool) → Sort u} (falseVal : motive Bool.false) (trueVal : motive Bool.true), @Eq.{u} (motive Bool.false) (@Bool.rec.{u} (fun (x : Bool) => motive x) falseVal trueVal Bool.false) falseVal) (∀ {motive : (t : Bool) → Sort u} (falseVal : motive Bool.false) (trueVal : motive Bool.true), @Eq.{u} (motive Bool.true) (@Bool.rec.{u} (fun (x : Bool) => motive x) falseVal trueVal Bool.true) trueVal) (fun {motive : (t : Bool) → Sort u} (falseVal : motive Bool.false) (trueVal : motive Bool.true) => @Eq.refl.{u} (motive Bool.false) (@Bool.rec.{u} (fun (x : Bool) => motive x) falseVal trueVal Bool.false)) fun {motive : (t : Bool) → Sort u} (falseVal : motive Bool.false) (trueVal : motive Bool.true) => @Eq.refl.{u} (motive Bool.true) (@Bool.rec.{u} (fun (x : Bool) => motive x) falseVal trueVal Bool.true)
👍 077_prodRecEqns
Reduction behavior of Prod.rec
theorem prodRecEqns.{u} : ∀ {α β : Type} {motive : Prod.{0, 0} α β → Sort u} (f : (a : α) → (b : β) → motive (@Prod.mk.{0, 0} α β a b)) (a : α) (b : β), @Eq.{u} (motive (@Prod.mk.{0, 0} α β a b)) (@Prod.rec.{u, 0, 0} α β (fun (x : Prod.{0, 0} α β) => motive x) f (@Prod.mk.{0, 0} α β a b)) (f a b) := fun {α β : Type} {motive : Prod.{0, 0} α β → Sort u} (f : (a : α) → (b : β) → motive (@Prod.mk.{0, 0} α β a b)) (a : α) (b : β) => @Eq.refl.{u} (motive (@Prod.mk.{0, 0} α β a b)) (@Prod.rec.{u, 0, 0} α β (fun (x : Prod.{0, 0} α β) => motive x) f (@Prod.mk.{0, 0} α β a b))
👍 078_nRecReduction
A proof relying on the reduction behavior of N.rec
def N.add : N → N → N := fun (t : N) => @N.rec.{1} (fun (x : N) => N → N) (fun (m : N) => m) (fun (n : N) (ih : N → N) (m : N) => N.succ (ih m)) t theorem nRecReduction : And (∀ (m : N), @Eq.{1} N (N.add N.zero m) m) (∀ (n m : N), @Eq.{1} N (N.add (N.succ n) m) (N.succ (N.add n m))) := @id.{0} (And (∀ (m : N), @Eq.{1} N (N.add N.zero m) m) (∀ (n m : N), @Eq.{1} N (N.add (N.succ n) m) (N.succ (N.add n m)))) (@And.intro (∀ (m : N), @Eq.{1} N (@N.rec.{1} (fun (x : N) => N → N) (fun (m : N) => m) (fun (n : N) (ih : N → N) (m : N) => N.succ (ih m)) N.zero m) m) (∀ (n m : N), @Eq.{1} N (@N.rec.{1} (fun (x : N) => N → N) (fun (m : N) => m) (fun (n : N) (ih : N → N) (m : N) => N.succ (ih m)) (N.succ n) m) (N.succ (@N.rec.{1} (fun (x : N) => N → N) (fun (m : N) => m) (fun (n : N) (ih : N → N) (m : N) => N.succ (ih m)) n m))) (fun (m : N) => @Eq.refl.{1} N (@N.rec.{1} (fun (x : N) => N → N) (fun (m : N) => m) (fun (n : N) (ih : N → N) (m : N) => N.succ (ih m)) N.zero m)) fun (n m : N) => @Eq.refl.{1} N (@N.rec.{1} (fun (x : N) => N → N) (fun (m : N) => m) (fun (n : N) (ih : N → N) (m : N) => N.succ (ih m)) (N.succ n) m))
👍 079_listRecReduction
Reduction behavior of List.rec
inductive List.{u} (α : Type u) : Type u constructor List.nil.{u} : {α : Type u} → List.{u} α constructor List.cons.{u} : {α : Type u} → (head : α) → (tail : List.{u} α) → List.{u} α def List.recOn.{u_1, u} : {α : Type u} → {motive : (t : List.{u} α) → Sort u_1} → (t : List.{u} α) → (nil : motive (@List.nil.{u} α)) → (cons : (head : α) → (tail : List.{u} α) → (tail_ih : motive tail) → motive (@List.cons.{u} α head tail)) → motive t := fun {α : Type u} {motive : (t : List.{u} α) → Sort u_1} (t : List.{u} α) (nil : motive (@List.nil.{u} α)) (cons : (head : α) → (tail : List.{u} α) → (tail_ih : motive tail) → motive (@List.cons.{u} α head tail)) => @List.rec.{u_1, u} α motive nil cons t def myListApped : {α : Type} → (xs ys : List.{0} α) → List.{0} α := fun {α : Type} (xs ys : List.{0} α) => @List.recOn.{1, 0} α (fun (x : List.{0} α) => List.{0} α) xs ys fun (x : α) (xs ih : List.{0} α) => @List.cons.{0} α x ih theorem listRecReduction : ∀ {α : Type} (xs ys : List.{0} α), And (@Eq.{1} (List.{0} α) (@myListApped α (@List.nil.{0} α) ys) ys) (∀ (x : α) (xs : List.{0} α), @Eq.{1} (List.{0} α) (@myListApped α (@List.cons.{0} α x xs) ys) (@List.cons.{0} α x (@myListApped α xs ys))) := fun {α : Type} (xs ys : List.{0} α) => @id.{0} (And (@Eq.{1} (List.{0} α) (@myListApped α (@List.nil.{0} α) ys) ys) (∀ (x : α) (xs : List.{0} α), @Eq.{1} (List.{0} α) (@myListApped α (@List.cons.{0} α x xs) ys) (@List.cons.{0} α x (@myListApped α xs ys)))) (@And.intro (@Eq.{1} (List.{0} α) (@List.recOn.{1, 0} α (fun (x : List.{0} α) => List.{0} α) (@List.nil.{0} α) ys fun (x : α) (xs ih : List.{0} α) => @List.cons.{0} α x ih) ys) (∀ (x : α) (xs : List.{0} α), @Eq.{1} (List.{0} α) (@List.recOn.{1, 0} α (fun (x : List.{0} α) => List.{0} α) (@List.cons.{0} α x xs) ys fun (x : α) (xs ih : List.{0} α) => @List.cons.{0} α x ih) (@List.cons.{0} α x (@List.recOn.{1, 0} α (fun (x : List.{0} α) => List.{0} α) xs ys fun (x : α) (xs ih : List.{0} α) => @List.cons.{0} α x ih))) (@Eq.refl.{1} (List.{0} α) (@List.recOn.{1, 0} α (fun (x : List.{0} α) => List.{0} α) (@List.nil.{0} α) ys fun (x : α) (xs ih : List.{0} α) => @List.cons.{0} α x ih)) fun (x : α) (xs : List.{0} α) => @Eq.refl.{1} (List.{0} α) (@List.recOn.{1, 0} α (fun (x : List.{0} α) => List.{0} α) (@List.cons.{0} α x xs) ys fun (x : α) (xs ih : List.{0} α) => @List.cons.{0} α x ih))
👍 080_RBTree.id_spec
Reduction behavior of RBTree.rec
def RBTree.id : {α : Type} → {c : Color} → {n : N} → (t : RBTree.{0} α c n) → RBTree.{0} α c n := fun {α : Type} {c : Color} {n : N} (t : RBTree.{0} α c n) => @RBTree.rec.{1, 0} α (fun (x : Color) (x_1 : N) (x_2 : RBTree.{0} α x x_1) => RBTree.{0} α x x_1) (@RBTree.leaf.{0} α) (fun {n : N} (_t1 : RBTree.{0} α Color.b n) (a : α) (_t2 ih1 ih2 : RBTree.{0} α Color.b n) => @RBTree.red.{0} α n ih1 a ih2) (fun {c1 c2 : Color} {n : N} (_t1 : RBTree.{0} α c1 n) (a : α) (_t2 : RBTree.{0} α c2 n) (ih1 : RBTree.{0} α c1 n) (ih2 : RBTree.{0} α c2 n) => @RBTree.black.{0} α c1 c2 n ih1 a ih2) c n t theorem RBTree.id_spec : ∀ {α : Type} {c : Color} {n : N} (t : RBTree.{0} α c n), @Eq.{1} (RBTree.{0} α c n) (@RBTree.id α c n t) t := fun {α : Type} {c : Color} {n : N} (t : RBTree.{0} α c n) => @RBTree.rec.{0, 0} α (fun {c : Color} {n : N} (t : RBTree.{0} α c n) => @Eq.{1} (RBTree.{0} α c n) (@RBTree.id α c n t) t) (@Eq.refl.{1} (RBTree.{0} α Color.b N.zero) (@RBTree.id α Color.b N.zero (@RBTree.leaf.{0} α))) (fun {n : N} (a : RBTree.{0} α Color.b n) (a_1 : α) (a_2 : RBTree.{0} α Color.b n) (a_ih : @Eq.{1} (RBTree.{0} α Color.b n) (@RBTree.id α Color.b n a) a) (a_ih_1 : @Eq.{1} (RBTree.{0} α Color.b n) (@RBTree.id α Color.b n a_2) a_2) => @id.{0} (@Eq.{1} (RBTree.{0} α Color.r n) (@RBTree.id α Color.r n (@RBTree.red.{0} α n a a_1 a_2)) (@RBTree.red.{0} α n a a_1 a_2)) ((@fun {α : Type} {n : N} (a a_3 : RBTree.{0} α Color.b n) (e_a : @Eq.{1} (RBTree.{0} α Color.b n) a a_3) => @Eq.rec.{0, 1} (RBTree.{0} α Color.b n) a (fun (a_4 : RBTree.{0} α Color.b n) (e_a : @Eq.{1} (RBTree.{0} α Color.b n) a a_4) => ∀ (a_5 a_6 : α), @Eq.{1} α a_5 a_6 → ∀ (a_7 a_8 : RBTree.{0} α Color.b n), @Eq.{1} (RBTree.{0} α Color.b n) a_7 a_8 → @Eq.{1} (RBTree.{0} α Color.r n) (@RBTree.red.{0} α n a a_5 a_7) (@RBTree.red.{0} α n a_4 a_6 a_8)) (fun (a_4 a_5 : α) (e_a : @Eq.{1} α a_4 a_5) => @Eq.rec.{0, 1} α a_4 (fun (a_6 : α) (e_a : @Eq.{1} α a_4 a_6) => ∀ (a_7 a_8 : RBTree.{0} α Color.b n), @Eq.{1} (RBTree.{0} α Color.b n) a_7 a_8 → @Eq.{1} (RBTree.{0} α Color.r n) (@RBTree.red.{0} α n a a_4 a_7) (@RBTree.red.{0} α n a a_6 a_8)) (fun (a_6 a_7 : RBTree.{0} α Color.b n) (e_a : @Eq.{1} (RBTree.{0} α Color.b n) a_6 a_7) => @Eq.rec.{0, 1} (RBTree.{0} α Color.b n) a_6 (fun (a_8 : RBTree.{0} α Color.b n) (e_a : @Eq.{1} (RBTree.{0} α Color.b n) a_6 a_8) => @Eq.{1} (RBTree.{0} α Color.r n) (@RBTree.red.{0} α n a a_4 a_6) (@RBTree.red.{0} α n a a_4 a_8)) (@Eq.refl.{1} (RBTree.{0} α Color.r n) (@RBTree.red.{0} α n a a_4 a_6)) a_7 e_a) a_5 e_a) a_3 e_a) α n (@RBTree.rec.{1, 0} α (fun (x : Color) (x_1 : N) (x_2 : RBTree.{0} α x x_1) => RBTree.{0} α x x_1) (@RBTree.leaf.{0} α) (fun {n : N} (_t1 : RBTree.{0} α Color.b n) (a : α) (_t2 ih1 ih2 : RBTree.{0} α Color.b n) => @RBTree.red.{0} α n ih1 a ih2) (fun {c1 c2 : Color} {n : N} (_t1 : RBTree.{0} α c1 n) (a : α) (_t2 : RBTree.{0} α c2 n) (ih1 : RBTree.{0} α c1 n) (ih2 : RBTree.{0} α c2 n) => @RBTree.black.{0} α c1 c2 n ih1 a ih2) Color.b n a) a a_ih a_1 a_1 (@Eq.refl.{1} α a_1) (@RBTree.rec.{1, 0} α (fun (x : Color) (x_1 : N) (x_2 : RBTree.{0} α x x_1) => RBTree.{0} α x x_1) (@RBTree.leaf.{0} α) (fun {n : N} (_t1 : RBTree.{0} α Color.b n) (a : α) (_t2 ih1 ih2 : RBTree.{0} α Color.b n) => @RBTree.red.{0} α n ih1 a ih2) (fun {c1 c2 : Color} {n : N} (_t1 : RBTree.{0} α c1 n) (a : α) (_t2 : RBTree.{0} α c2 n) (ih1 : RBTree.{0} α c1 n) (ih2 : RBTree.{0} α c2 n) => @RBTree.black.{0} α c1 c2 n ih1 a ih2) Color.b n a_2) a_2 a_ih_1)) (fun {c1 c2 : Color} {n : N} (a : RBTree.{0} α c1 n) (a_1 : α) (a_2 : RBTree.{0} α c2 n) (a_ih : @Eq.{1} (RBTree.{0} α c1 n) (@RBTree.id α c1 n a) a) (a_ih_1 : @Eq.{1} (RBTree.{0} α c2 n) (@RBTree.id α c2 n a_2) a_2) => @id.{0} (@Eq.{1} (RBTree.{0} α Color.b (N.succ n)) (@RBTree.id α Color.b (N.succ n) (@RBTree.black.{0} α c1 c2 n a a_1 a_2)) (@RBTree.black.{0} α c1 c2 n a a_1 a_2)) ((@fun {α : Type} {c1 c2 : Color} {n : N} (a a_3 : RBTree.{0} α c1 n) (e_a : @Eq.{1} (RBTree.{0} α c1 n) a a_3) => @Eq.rec.{0, 1} (RBTree.{0} α c1 n) a (fun (a_4 : RBTree.{0} α c1 n) (e_a : @Eq.{1} (RBTree.{0} α c1 n) a a_4) => ∀ (a_5 a_6 : α), @Eq.{1} α a_5 a_6 → ∀ (a_7 a_8 : RBTree.{0} α c2 n), @Eq.{1} (RBTree.{0} α c2 n) a_7 a_8 → @Eq.{1} (RBTree.{0} α Color.b (N.succ n)) (@RBTree.black.{0} α c1 c2 n a a_5 a_7) (@RBTree.black.{0} α c1 c2 n a_4 a_6 a_8)) (fun (a_4 a_5 : α) (e_a : @Eq.{1} α a_4 a_5) => @Eq.rec.{0, 1} α a_4 (fun (a_6 : α) (e_a : @Eq.{1} α a_4 a_6) => ∀ (a_7 a_8 : RBTree.{0} α c2 n), @Eq.{1} (RBTree.{0} α c2 n) a_7 a_8 → @Eq.{1} (RBTree.{0} α Color.b (N.succ n)) (@RBTree.black.{0} α c1 c2 n a a_4 a_7) (@RBTree.black.{0} α c1 c2 n a a_6 a_8)) (fun (a_6 a_7 : RBTree.{0} α c2 n) (e_a : @Eq.{1} (RBTree.{0} α c2 n) a_6 a_7) => @Eq.rec.{0, 1} (RBTree.{0} α c2 n) a_6 (fun (a_8 : RBTree.{0} α c2 n) (e_a : @Eq.{1} (RBTree.{0} α c2 n) a_6 a_8) => @Eq.{1} (RBTree.{0} α Color.b (N.succ n)) (@RBTree.black.{0} α c1 c2 n a a_4 a_6) (@RBTree.black.{0} α c1 c2 n a a_4 a_8)) (@Eq.refl.{1} (RBTree.{0} α Color.b (N.succ n)) (@RBTree.black.{0} α c1 c2 n a a_4 a_6)) a_7 e_a) a_5 e_a) a_3 e_a) α c1 c2 n (@RBTree.rec.{1, 0} α (fun (x : Color) (x_1 : N) (x_2 : RBTree.{0} α x x_1) => RBTree.{0} α x x_1) (@RBTree.leaf.{0} α) (fun {n : N} (_t1 : RBTree.{0} α Color.b n) (a : α) (_t2 ih1 ih2 : RBTree.{0} α Color.b n) => @RBTree.red.{0} α n ih1 a ih2) (fun {c1 c2 : Color} {n : N} (_t1 : RBTree.{0} α c1 n) (a : α) (_t2 : RBTree.{0} α c2 n) (ih1 : RBTree.{0} α c1 n) (ih2 : RBTree.{0} α c2 n) => @RBTree.black.{0} α c1 c2 n ih1 a ih2) c1 n a) a a_ih a_1 a_1 (@Eq.refl.{1} α a_1) (@RBTree.rec.{1, 0} α (fun (x : Color) (x_1 : N) (x_2 : RBTree.{0} α x x_1) => RBTree.{0} α x x_1) (@RBTree.leaf.{0} α) (fun {n : N} (_t1 : RBTree.{0} α Color.b n) (a : α) (_t2 ih1 ih2 : RBTree.{0} α Color.b n) => @RBTree.red.{0} α n ih1 a ih2) (fun {c1 c2 : Color} {n : N} (_t1 : RBTree.{0} α c1 n) (a : α) (_t2 : RBTree.{0} α c2 n) (ih1 : RBTree.{0} α c1 n) (ih2 : RBTree.{0} α c2 n) => @RBTree.black.{0} α c1 c2 n ih1 a ih2) c2 n a_2) a_2 a_ih_1)) c n t
👍 081_And.right
Type-checking simple projection functions
👍 082_Prod.snd
Type-checking projection functions with parameters
def Prod.fst.{u, v} : {α : Type u} → {β : Type v} → (self : Prod.{u, v} α β) → α := fun (α : Type u) (β : Type v) (self : Prod.{u, v} α β) => self.1 def Prod.snd.{u, v} : {α : Type u} → {β : Type v} → (self : Prod.{u, v} α β) → β := fun (α : Type u) (β : Type v) (self : Prod.{u, v} α β) => self.2
👍 083_PProd.snd
Type-checking projection functions
def PProd.fst.{u, v} : {α : Sort u} → {β : Sort v} → (self : PProd.{u, v} α β) → α := fun (α : Sort u) (β : Sort v) (self : PProd.{u, v} α β) => self.1 def PProd.snd.{u, v} : {α : Sort u} → {β : Sort v} → (self : PProd.{u, v} α β) → β := fun (α : Sort u) (β : Sort v) (self : PProd.{u, v} α β) => self.2
👍 084_PSigma.snd
Type-checking dependent projection functions
inductive PSigma.{u, v} {α : Sort u} (β : α → Sort v) : Sort (max (max 1 u) v) constructor PSigma.mk.{u, v} : {α : Sort u} → {β : α → Sort v} → (fst : α) → (snd : β fst) → @PSigma.{u, v} α β def PSigma.fst.{u, v} : {α : Sort u} → {β : α → Sort v} → (self : @PSigma.{u, v} α β) → α := fun (α : Sort u) (β : α → Sort v) (self : @PSigma.{u, v} α β) => self.1 def PSigma.snd.{u, v} : {α : Sort u} → {β : α → Sort v} → (self : @PSigma.{u, v} α β) → β (@PSigma.fst.{u, v} α β self) := fun (α : Sort u) (β : α → Sort v) (self : @PSigma.{u, v} α β) => self.2
✋ 085_projOutOfRange
Out of range projection
✋ 086_projNotStruct
Projection out something that is not a structure
👍 087_projProp1
Projecting out of a proposition
The lean kernel allows projections out of propositions if they precede all dependent data fields.
inductive PropStructure.{u, v} : Prop constructor PropStructure.mk.{u, v} : ∀ (aProof : PUnit.{u}) (someData : PUnit.{v}) (aSecondProof : PUnit.{u}) (someMoreData : PUnit.{v}) (aProofAboutData : @Eq.{v} PUnit.{v} someMoreData someMoreData) (aFinalProof : PUnit.{u}), PropStructure.{u, v} def projProp1 : ∀ (x : PropStructure.{0, 1}), PUnit.{0} := fun (x : PropStructure.{0, 1}) => x.1
✋ 088_projProp2
Projecting out of a proposition
The lean kernel disallows data projections out of propositional structures.
def projProp2 : (x : PropStructure.{0, 1}) → PUnit.{1} := fun (x : PropStructure.{0, 1}) => x.2
👍 089_projProp3
Projecting out of a proposition
The lean kernel allows projections out of propositions if they precede all dependent data fields. Non-dependent data fields are not relevant.
def projProp3 : ∀ (x : PropStructure.{0, 1}), PUnit.{0} := fun (x : PropStructure.{0, 1}) => x.3
✋ 090_projProp4
Projecting out of a proposition
The lean kernel disallows data projections out of propositional structures.
def projProp4 : (x : PropStructure.{0, 1}) → PUnit.{1} := fun (x : PropStructure.{0, 1}) => x.4
✋ 091_projProp5
Projecting out of a proposition
The lean kernel disallows proof projections out of propositional structures that depend on data.
def projProp5 : ∀ (x : PropStructure.{0, 1}), @Eq.{1} PUnit.{1} x.4 x.4 := fun (x : PropStructure.{0, 1}) => x.5
✋ 092_projProp6
Projecting out of a proposition.
The lean kernel rejects any projections out of a proposition that come after a dependent data field, even if that is not used by the present projection.
def projProp6 : ∀ (x : PropStructure.{0, 1}), PUnit.{0} := fun (x : PropStructure.{0, 1}) => x.6
👍 093_projDataIndexRec
The recursor for ProjDataIndex allows elimination into sort.
inductive True : Prop constructor True.intro : True inductive ProjDataIndex (a._@._internal._hyg.0 : N) : Prop constructor ProjDataIndex.mk : ∀ (n : N) (p : True), ProjDataIndex n def projDataIndexRec.{u_1} : {a : N} → {motive : (t : ProjDataIndex a) → Sort u_1} → (mk : (p : True) → motive (ProjDataIndex.mk a p)) → (t : ProjDataIndex a) → motive t := @ProjDataIndex.rec.{u_1}
✋ 094_projIndexData
Projecting out data is not allowed, even if this data appears as an index and the recursor would allow it.
def projIndexData : (x : N) → (x : ProjDataIndex x) → N := fun (x : N) (x_1 : ProjDataIndex x) => x_1.1
✋ 095_projIndexData2
Projecting out data is not allowed, even if this data appears as an index and the recursor would allow it.
This also forbids projecting out proofs that follow such fields.
def projIndexData2 : ∀ (x : N) (x : ProjDataIndex x), True := fun (x : N) (x_1 : ProjDataIndex x) => x_1.2
👍 096_projRed
Projection reductions
def projRed : @Eq.{1} Bool (@Prod.snd.{0, 0} Bool Bool (@Prod.mk.{0, 0} Bool Bool Bool.true Bool.false)) Bool.false := @rfl.{1} Bool (@Prod.snd.{0, 0} Bool Bool (@Prod.mk.{0, 0} Bool Bool Bool.true Bool.false))
👍 097_ruleK
Rule k for Eq:
The recursor reduces even if the major argument is not a constructor,
as long replacing the major argument with a constructor is type correct.
✋ 098_ruleKbad
Rule k for Eq should not fire if the types of the major argument
do not match that of the constructor.
theorem ruleKbad : ∀ (h : @Eq.{1} Bool Bool.true Bool.false) (a : Bool), @Eq.{1} Bool (@Eq.rec.{1, 1} Bool Bool.true (fun (x : Bool) (x_1 : @Eq.{1} Bool Bool.true x) => Bool) a Bool.false h) a := fun (x : @Eq.{1} Bool Bool.true Bool.false) (a : Bool) => @Eq.refl.{1} Bool a
✋ 099_ruleKAcc
Rule k should not fire for Acc.
inductive Acc.{u} {α : Sort u} (r : α → α → Prop) : α → Prop constructor Acc.intro.{u} : ∀ {α : Sort u} {r : α → α → Prop} (x : α) (h : ∀ (y : α), r y x → @Acc.{u} α r y), @Acc.{u} α r x theorem ruleKAcc.{u} : ∀ (α : Sort u) (p : α → α → Prop) (x : α) (h : @Acc.{u} α p x) (a : Bool), @Eq.{1} Bool (@Acc.rec.{1, u} α p (fun (x : α) (x_1 : @Acc.{u} α p x) => Bool) (fun (x : α) (x_1 : ∀ (y : α), p y x → @Acc.{u} α p y) (x_2 : (y : α) → (a : p y x) → (fun (x : α) (x_2 : @Acc.{u} α p x) => Bool) y (x_1 y a)) => a) x h) a := fun (α : Sort u) (p : α → α → Prop) (x : α) (h : @Acc.{u} α p x) (a : Bool) => @Eq.refl.{1} Bool a
👍 100_aNatLit
Type checking Nat literals
👍 101_natLitEq
Reducing Nat literals
theorem natLitEq : failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation) := failed to pretty print expression (use 'set_option pp.rawOnError true' for raw representation)
👍 102_proofIrrelevance
Proof irrelevance: every Prop is a subsingleton, if p : Prop then all elements of p
are definitionally equal.
✋ 103_proofIrrelevanceBad
Proof irrelevance is limited to Prop: if p : Type, then all elements of p are not
definitionally equal.
👍 104_proofIrrelevanceWhnf
Proof irrelevance: if p : A and A is definitionally equal to Prop, then all elements of p
are still definitionally equal. Just applying proof irrelevance at Sort 0 isn't sufficient.
👍 105_unitEta1
Unit eta
👍 106_unitEta2
Unit eta
👍 107_unitEta3
Unit eta
✋ 108_indexedUnitEta
The unit-like rule, which makes any two elements of a single-constructor type with
no fields definitionally equal, is also restricted to non-recursive structures
without indices (is_def_eq_unit_like goes through is_non_rec_structure), so it
does not fire for IndexedUnit.
inductive IndexedUnit : Bool → Type constructor IndexedUnit.mk : IndexedUnit Bool.true def indexedUnitEta : ∀ (x y : IndexedUnit Bool.true), @Eq.{1} (IndexedUnit Bool.true) x y := fun (x y : IndexedUnit Bool.true) => @Eq.refl.{1} (IndexedUnit Bool.true) x
👍 109_structEta
Structure eta
def structEta.{u} : ∀ (α β : Type u) (x : Prod.{u, u} α β), And (@Eq.{u + 1} (Prod.{u, u} α β) x (@Prod.mk.{u, u} α β (@Prod.fst.{u, u} α β x) (@Prod.snd.{u, u} α β x))) (@Eq.{u + 1} (Prod.{u, u} α β) (@Prod.mk.{u, u} α β (@Prod.fst.{u, u} α β x) (@Prod.snd.{u, u} α β x)) x) := fun (x x_1 : Type u) (x_2 : Prod.{u, u} x x_1) => @And.intro (@Eq.{u + 1} (Prod.{u, u} x x_1) x_2 (@Prod.mk.{u, u} x x_1 (@Prod.fst.{u, u} x x_1 x_2) (@Prod.snd.{u, u} x x_1 x_2))) (@Eq.{u + 1} (Prod.{u, u} x x_1) (@Prod.mk.{u, u} x x_1 (@Prod.fst.{u, u} x x_1 x_2) (@Prod.snd.{u, u} x x_1 x_2)) x_2) (@rfl.{u + 1} (Prod.{u, u} x x_1) x_2) (@rfl.{u + 1} (Prod.{u, u} x x_1) (@Prod.mk.{u, u} x x_1 (@Prod.fst.{u, u} x x_1 x_2) (@Prod.snd.{u, u} x x_1 x_2)))
✋ 110_indexedStructEta
Structure eta applies only to non-recursive structures without indices: the
official kernel's is_non_rec_structure requires nindices == 0, so it does not
fire for IndexedSingleton even though that has a single constructor.
Every field of IndexedSingleton.mk is a proof, so a kernel that checks only
"has a single constructor" and then compares the fields against projections
would have proof irrelevance discharge the remaining goals, and would wrongly
accept this.
inductive IndexedSingleton : Bool → Type constructor IndexedSingleton.mk : True → IndexedSingleton Bool.true def indexedStructEta : ∀ (x : IndexedSingleton Bool.true), @Eq.{1} (IndexedSingleton Bool.true) (IndexedSingleton.mk True.intro) x := fun (x : IndexedSingleton Bool.true) => @Eq.refl.{1} (IndexedSingleton Bool.true) x
👍 111_funEta
Function eta for non-dependent functions.
👍 112_funEtaDep
Function eta for dependent functions (pi types).
✋ 113_funEtaBad
Eta should not identify functions with different bodies.
theorem funEtaBad : ∀ (α β : Type) (g : α → α) (f : α → β), @Eq.{1} ((x : α) → β) (fun (x : α) => f (g x)) f := fun (x x_1 : Type) (x_2 : x → x) (f : x → x_1) => @Eq.refl.{1} ((x : x) → x_1) f
✋ 114_etaRuleK
Corner case for function eta: Does a defeq between a partially applied recursor with rule k and a free variable trigger eta expansion?
Taking the official kernel as the specification, the answer is no. See https://github.com/leanprover/lean4/issues/12520 for a discussion.
def etaRuleK : ∀ (a : @Eq.{1} Bool Bool.true Bool.true → Bool), @Eq.{1} (@Eq.{1} Bool Bool.true Bool.true → Bool) (@Eq.rec.{1, 1} Bool Bool.true (fun (x : Bool) (x_1 : @Eq.{1} Bool Bool.true x) => Bool) (a (@Eq.refl.{1} Bool Bool.true)) Bool.true) a := fun (a : @Eq.{1} Bool Bool.true Bool.true → Bool) => @Eq.refl.{1} (@Eq.{1} Bool Bool.true Bool.true → Bool) a
✋ 115_etaCtor
Corner case for function eta: Does a defeq between a partially applied constructor trigger eta expansion?
Taking the official kernel as the specification, the answer is no. See https://github.com/leanprover/lean4/issues/12520 for a discussion.
inductive T : Type constructor T.mk : (val : Bool) → (proof : True) → T def T.val : (self : T) → Bool := fun (self : T) => self.1 def etaCtor : ∀ (x : (proof : True) → T), @Eq.{1} ((proof : True) → T) (T.mk (T.val (x True.intro))) x := fun (x : (proof : True) → T) => @Eq.refl.{1} ((proof : True) → T) x
✋ 116_reflOccLeft
Rejection: recursive occurrence on the left of an arrow, behind further arrows inside a constructor argument.
The constructor argument is a function type Nat → (I → Nat).
inductive reflOccLeft : Type constructor reflOccLeft.mk : (x : (x : Nat) → (x : reflOccLeft) → Nat) → reflOccLeft
✋ 117_reflOccInIndex
Rejection: recursive occurrence in index position, behind a further arrow.
We build an indexed inductive I : Type → Type with a constructor argument
Nat → I (I α), so the recursive occurrence appears as an index argument.
inductive reflOccInIndex : (α : Type) → Type constructor reflOccInIndex.mk : (α : Type) → (x : (x : Nat) → reflOccInIndex (reflOccInIndex x)) → reflOccInIndex α
👍 118_reduceCtorParamRefl.mk
When checking inductives, we expect the kernel to reduce the types of constructor arguments in all positive positions.
inductive reduceCtorParamRefl (a._@._internal._hyg.0 : Type) : Type constructor reduceCtorParamRefl.mk : (α : @id.{3} (Type 1) Type) → (x : (x : α) → constType (reduceCtorParamRefl α) (reduceCtorParamRefl α)) → reduceCtorParamRefl α
👍 119_reduceCtorParamRefl2.mk
When checking inductives, we expect the kernel to reduce the types of constructor arguments in all positive positions.
inductive reduceCtorParamRefl2 (a._@._internal._hyg.0 : Type) : Type constructor reduceCtorParamRefl2.mk : (α : @id.{3} (Type 1) Type) → (x : (x : α) → constType (reduceCtorParamRefl2 α) α) → reduceCtorParamRefl2 α
👍 120_rTreeRec
Asserting the type of the generated recursor.
inductive RTree : Type constructor RTree.leaf : RTree constructor RTree.node : (children : Bool → RTree) → RTree def rTreeRec.{u_1} : {motive : (t : RTree) → Sort u_1} → (leaf : motive RTree.leaf) → (node : (children : Bool → RTree) → (children_ih : (a : Bool) → motive (children a)) → motive (RTree.node children)) → (t : RTree) → motive t := @RTree.rec.{u_1}
👍 121_rtreeRecReduction
Reduction behavior of RTree.rec on RTree.mk.
def RTree.left : (t : RTree) → RTree := fun (t : RTree) => @RTree.rec.{1} (fun (x : RTree) => RTree) RTree.leaf (fun (children : Bool → RTree) (_ih : (a : Bool) → (fun (x : RTree) => RTree) (children a)) => children Bool.true) t theorem rtreeRecReduction : ∀ (t1 t2 : RTree), @Eq.{1} RTree (RTree.left (RTree.node fun (t : Bool) => @Bool.rec.{1} (fun (x : Bool) => RTree) t2 t1 t)) t1 := fun (x x_1 : RTree) => @rfl.{1} RTree (RTree.left (RTree.node fun (t : Bool) => @Bool.rec.{1} (fun (x : Bool) => RTree) x_1 x t))
👍 122_accRecType
Asserting the type of Acc.rec.
def accRecType.{u_1, u_2} : {α : Sort u_1} → {r : α → α → Prop} → {motive : (a : α) → (t : @Acc.{u_1} α r a) → Sort u_2} → (intro : (x : α) → (h : ∀ (y : α), r y x → @Acc.{u_1} α r y) → (h_ih : (y : α) → (a : r y x) → motive y (h y a)) → motive x (@Acc.intro.{u_1} α r x h)) → {a : α} → (t : @Acc.{u_1} α r a) → motive a t := @Acc.rec.{u_2, u_1}
👍 123_accRecReduction
Acc.rec reduces on Acc.intro.
theorem accRecReduction : ∀ {α : Type} (r : α → α → Prop) (a : α) (h : ∀ (b : α), r b a → @Acc.{1} α r b) (p : Bool), @Eq.{1} Bool (@Acc.rec.{1, 1} α r (fun (x : α) (x_1 : @Acc.{1} α r x) => Bool) (fun (x : α) (x_1 : ∀ (y : α), r y x → @Acc.{1} α r y) (x_2 : (y : α) → (a : r y x) → (fun (x : α) (x_2 : @Acc.{1} α r x) => Bool) y (x_1 y a)) => p) a (@Acc.intro.{1} α r a h)) p := fun {α : Type} (r : α → α → Prop) (a : α) (h : ∀ (b : α), r b a → @Acc.{1} α r b) (p : Bool) => @Eq.refl.{1} Bool (@Acc.rec.{1, 1} α r (fun (x : α) (x_1 : @Acc.{1} α r x) => Bool) (fun (x : α) (x_1 : ∀ (y : α), r y x → @Acc.{1} α r y) (x_2 : (y : α) → (a : r y x) → (fun (x : α) (x_2 : @Acc.{1} α r x) => Bool) y (x_1 y a)) => p) a (@Acc.intro.{1} α r a h))
✋ 124_accRecNoEta
Acc.rec does not have structure eta.
theorem accRecNoEta : ∀ {α : Type} (r : α → α → Prop) (a : α) (h : @Acc.{1} α r a) (p : Bool), @Eq.{1} Bool (@Acc.rec.{1, 1} α r (fun (x : α) (x_1 : @Acc.{1} α r x) => Bool) (fun (x : α) (x_1 : ∀ (y : α), r y x → @Acc.{1} α r y) (x_2 : (y : α) → (a : r y x) → (fun (x : α) (x_2 : @Acc.{1} α r x) => Bool) y (x_1 y a)) => p) a h) p := fun (α : Type) (r : α → α → Prop) (a : α) (h : @Acc.{1} α r a) (p : Bool) => @Eq.refl.{1} Bool p
👍 125_quotMkType
Asserting the type of Quot.mk.
quot Quot.{u} : {α : Sort u} → (r : α → α → Prop) → Sort u quot Quot.mk.{u} : {α : Sort u} → (r : α → α → Prop) → (a : α) → @Quot.{u} α r quot Quot.lift.{u, v} : {α : Sort u} → {r : α → α → Prop} → {β : Sort v} → (f : (a : α) → β) → (a : ∀ (a b : α) (a_1 : r a b), @Eq.{v} β (f a) (f b)) → (a : @Quot.{u} α r) → β quot Quot.ind.{u} : ∀ {α : Sort u} {r : α → α → Prop} {β : (a : @Quot.{u} α r) → Prop} (mk : ∀ (a : α), β (@Quot.mk.{u} α r a)) (q : @Quot.{u} α r), β q def quotMkType.{u} : {α : Sort u} → (r : α → α → Prop) → (a : α) → @Quot.{u} α r := @Quot.mk.{u}
👍 126_quotIndType
Asserting the type of Quot.ind.
def quotIndType.{u} : ∀ {α : Sort u} {r : α → α → Prop} {β : (a : @Quot.{u} α r) → Prop} (mk : ∀ (a : α), β (@Quot.mk.{u} α r a)) (q : @Quot.{u} α r), β q := @Quot.ind.{u}
👍 127_quotLiftType
Asserting the type of Quot.lift.
def quotLiftType.{u, v} : {α : Sort u} → {r : α → α → Prop} → {β : Sort v} → (f : (a : α) → β) → (a : ∀ (a b : α) (a_1 : r a b), @Eq.{v} β (f a) (f b)) → (a : @Quot.{u} α r) → β := @Quot.lift.{u, v}
👍 128_quotSoundType
Asserting the type of Quot.sound.
axiom Quot.sound.{u} : ∀ {α : Sort u} {r : α → α → Prop} {a b : α}, r a b → @Eq.{u} (@Quot.{u} α r) (@Quot.mk.{u} α r a) (@Quot.mk.{u} α r b) def quotSoundType.{u} : ∀ {α : Sort u} {r : α → α → Prop} {a b : α}, r a b → @Eq.{u} (@Quot.{u} α r) (@Quot.mk.{u} α r a) (@Quot.mk.{u} α r b) := @Quot.sound.{u}
👍 129_quotLiftReduction
Reduction behavior of Quot.lift on Quot.mk.
theorem quotLiftReduction.{u, v} : ∀ {α : Sort u} {r : α → α → Prop} {β : Sort v} (f : (a : α) → β) (h : ∀ (a b : α) (a_1 : r a b), @Eq.{v} β (f a) (f b)) (a : α), @Eq.{v} β (@Quot.lift.{u, v} α r β f h (@Quot.mk.{u} α r a)) (f a) := fun {α : Sort u} {r : α → α → Prop} {β : Sort v} (f : (a : α) → β) (h : ∀ (a b : α) (a_1 : r a b), @Eq.{v} β (f a) (f b)) (a : α) => @Eq.refl.{v} β (@Quot.lift.{u, v} α r β f h (@Quot.mk.{u} α r a))
👍 130_quotIndReduction
Reduction behavior of Quot.ind on Quot.mk.
theorem quotIndReduction.{u} : ∀ {α : Sort u} (r : α → α → Prop) {β : (a : @Quot.{u} α r) → Prop} (mk : ∀ (a : α), β (@Quot.mk.{u} α r a)) (a : α), @Eq.{0} (β (@Quot.mk.{u} α r a)) (@Quot.ind.{u} α r β mk (@Quot.mk.{u} α r a)) (mk a) := fun {α : Sort u} (r : α → α → Prop) {β : (a : @Quot.{u} α r) → Prop} (mk : ∀ (a : α), β (@Quot.mk.{u} α r a)) (a : α) => @Eq.refl.{0} (β (@Quot.mk.{u} α r a)) (@Quot.ind.{u} α r β mk (@Quot.mk.{u} α r a))
✋ 131_dup_defs
Two definitions with the same name
def dup_defs : Type := Prop
✋ 132_dup_ind_def
A definition and a constructor with the same name
inductive dup_ind_def : Type constructor dup_ind_def.mk : dup_ind_def
✋ 133_dup_ctor_def
A definition and a constructor with the same name
constructor dup_ctor_def.mk : dup_ctor_def inductive dup_ctor_def : Type
✋ 134_dup_rec_def
A definition and a recursor with the same name
inductive dup_rec_def : Type constructor dup_rec_def.mk : dup_rec_def
✋ 135_misnamed_rec_user
The name of the recursor for misnamed_rec must be misnamed_rec.rec:
another name (like misnamed_rec.not_rec) should be rejected.
dupRecUser is included so that checkers that recreate the recursor (as misnamed_rec.rec)
rather than validating it still fail, because misnamed_rec_user references misnamed_rec.not_rec.
inductive misnamed_rec : Type constructor misnamed_rec.mk : misnamed_rec def misnamed_rec_user.{u_1} : {motive : (t : misnamed_rec) → Sort u_1} → (mk : motive misnamed_rec.mk) → (t : misnamed_rec) → motive t := @misnamed_rec.not_rec.{u_1}
✋ 136_dup_rec_def2
Even if a kernel doesn't catch a recursor for dup_rec_def2 that is misnamed
as dup_rec_def2.not_rec, it should catch some other constant being given
the name dup_rec_def2.rec that is reserved for the recursor.
def dup_rec_def2.rec : Type := Prop inductive dup_rec_def2 : Type constructor dup_rec_def2.mk : dup_rec_def2
✋ 137_dup_ctor_rec
A constructor and a recursor with the same name
inductive dup_ctor_rec : Type
✋ 138_DupConCon
An inductive with two constructors with the same name
inductive DupConCon : Type constructor dup_ind_con_con.mk : DupConCon