This PR generates `.ctorIdx` functions for all inductive types, not just enumeration types. This can be a building block for other constructions (`BEq`, `noConfusion`) that are size-efficient even for large inductives. It also renames it from `.toCtorIdx` to `.ctorIdx`, which is the more idiomatic naming. The old name exists as an alias, with a deprecation attribute to be added after the next stage0 update. These functions can arguably compiled down to a rather efficient tag lookup, rather than a `case` statement. This is future work (but hopefully near future). For a fair number of basic types the compiler is not able to compile a function using `casesOn` until further definitions have been defined. This therefore (ab)uses the `genInjectivity` flag and `gen_injective_theorems%` command to also control the generation of this construct. For (slightly) more efficient kernel reduction one could use `.rec` rather than `.casesOn`. I did not do that yet, also because it complicates compilation.
35 lines
1.1 KiB
Text
35 lines
1.1 KiB
Text
def filter (p : α → Prop) [inst : DecidablePred p] (xs : List α) : List α :=
|
||
match xs with
|
||
| [] => []
|
||
| x :: xs' =>
|
||
if p x then
|
||
-- Trying to confuse `omega` by creating subterms that are structurally different
|
||
-- but definitionally equal.
|
||
x :: @filter α p (fun x => inst x) xs'
|
||
else
|
||
@filter α p inst xs'
|
||
|
||
def filter_length (p : α → Prop) [DecidablePred p] : (filter p xs).length ≤ xs.length := by
|
||
induction xs with
|
||
| nil => simp [filter]
|
||
| cons x xs ih =>
|
||
simp only [filter]
|
||
split <;> simp only [List.length] <;> omega
|
||
|
||
inductive Op where
|
||
| bla
|
||
| foo (a : Nat)
|
||
|
||
def Op.fooData (o : Op) (h : o.ctorIdx = 1) : Nat :=
|
||
match o, h with
|
||
| .foo a, _ => a
|
||
|
||
theorem ex (o₁ o₂ o₃ : Op)
|
||
(h₁ : o₁.ctorIdx = 1)
|
||
(h₂ : o₁.ctorIdx = o₂.ctorIdx)
|
||
(h₃ : o₂.ctorIdx = o₃.ctorIdx)
|
||
(h₄ : o₂.ctorIdx = 1)
|
||
(_ : o₁.fooData h₁ < o₂.fooData h₄)
|
||
(_ : o₂.fooData (h₂ ▸ h₁) < o₃.fooData (h₃ ▸ h₄))
|
||
: o₁.fooData h₁ < o₃.fooData (h₃ ▸ h₄) := by
|
||
omega
|