This PR changes the order of steps tried when proving equational theorems for structural recursion. In order to avoid goals that `split` cannot handle, avoid unfolding the LHS of the equation to `.brecOn` and `.rec` until after the RHS has been split into its final cases. Fixes: #10195
103 lines
3.5 KiB
Text
103 lines
3.5 KiB
Text
inductive Vec (α : Type u) : Nat → Type u
|
||
| nil : Vec α 0
|
||
| cons : α → {n : Nat} → Vec α n → Vec α (n+1)
|
||
|
||
-- set_option trace.split.failure true
|
||
-- set_option trace.split.debug true
|
||
-- set_option trace.Elab.definition.structural.eqns true
|
||
|
||
def decEqVecPlain {α} {a} [DecidableEq α] (x : @Vec α a) (x_1 : @Vec α a) : Decidable (x = x_1) :=
|
||
if h : Vec.ctorIdx x = Vec.ctorIdx x_1 then
|
||
match x, x_1, h with
|
||
| Vec.nil, Vec.nil, _ => isTrue rfl
|
||
| Vec.cons a_1 a_2, Vec.cons b b_1, _ =>
|
||
if h_1 : @a_1 = @b then by
|
||
subst h_1
|
||
exact
|
||
let inst := decEqVecPlain @a_2 @b_1;
|
||
if h_2 : @a_2 = @b_1 then by subst h_2; exact isTrue rfl
|
||
else isFalse (by intro n; injection n; apply h_2 _; assumption)
|
||
else isFalse (by intro n_1; injection n_1; apply h_1 _; assumption)
|
||
else isFalse (fun h' => h (congrArg Vec.ctorIdx h'))
|
||
termination_by structural x
|
||
|
||
-- Splitter and eqns generated just fine
|
||
#guard_msgs(drop info) in
|
||
#print sig decEqVecPlain.match_1
|
||
#guard_msgs(drop info) in
|
||
#print sig decEqVecPlain.match_1.eq_1
|
||
|
||
/--
|
||
info: theorem decEqVecPlain.eq_def.{u_1} : ∀ {α : Type u_1} {a : Nat} [inst : DecidableEq α] (x x_1 : Vec α a),
|
||
decEqVecPlain x x_1 =
|
||
if h : x.ctorIdx = x_1.ctorIdx then
|
||
match a, x, x_1, h with
|
||
| .(0), Vec.nil, Vec.nil, x => isTrue ⋯
|
||
| .(n + 1), Vec.cons a_1 a_2, Vec.cons b b_1, x =>
|
||
if h_1 : a_1 = b then
|
||
Eq.ndrec (motive := fun b =>
|
||
(Vec.cons a_1 a_2).ctorIdx = (Vec.cons b b_1).ctorIdx → Decidable (Vec.cons a_1 a_2 = Vec.cons b b_1))
|
||
(fun x =>
|
||
have inst_1 := decEqVecPlain a_2 b_1;
|
||
if h_2 : a_2 = b_1 then
|
||
Eq.ndrec (motive := fun b_1 =>
|
||
(Vec.cons a_1 a_2).ctorIdx = (Vec.cons a_1 b_1).ctorIdx →
|
||
have inst := decEqVecPlain a_2 b_1;
|
||
Decidable (Vec.cons a_1 a_2 = Vec.cons a_1 b_1))
|
||
(fun x =>
|
||
have inst := decEqVecPlain a_2 a_2;
|
||
isTrue ⋯)
|
||
h_2 x
|
||
else isFalse ⋯)
|
||
h_1 x
|
||
else isFalse ⋯
|
||
else isFalse ⋯
|
||
-/
|
||
#guard_msgs(pass trace, all) in
|
||
#print sig decEqVecPlain.eq_def
|
||
|
||
|
||
axiom testSorry : α
|
||
|
||
inductive I : Nat → Type u | cons : I n → I (n + 1)
|
||
axiom P : I n → Prop
|
||
@[instance] axiom instDecEqI : ∀ (x : I n), Decidable (P x)
|
||
axiom R : I n → Type
|
||
set_option trace.split.failure true in
|
||
noncomputable def foo (x x' : I n) : R x :=
|
||
if h : P x then
|
||
match (generalizing := false) x, x', id h with --NB: non-FVar discr
|
||
| .cons a_2, .cons a_2', _ => (testSorry : _ → _ → _) (foo a_2 a_2') h
|
||
else testSorry
|
||
termination_by structural x
|
||
|
||
|
||
/--
|
||
info: theorem foo.eq_def.{u_1, u_2} : ∀ {n : Nat} (x : I n) (x' : I n),
|
||
foo x x' =
|
||
if h : P x then
|
||
match n, x, x', ⋯ with
|
||
| .(n_1 + 1), a_2.cons, a_2'.cons, x_1 => testSorry (foo a_2 a_2') h
|
||
else testSorry
|
||
-/
|
||
#guard_msgs(pass trace, all) in
|
||
#print sig foo.eq_def
|
||
|
||
|
||
noncomputable def nondep (x x' : I n) : Bool :=
|
||
if h : P x then
|
||
match (generalizing := false) x, x', id h with --NB: non-FVar discr
|
||
| .cons a_2, .cons a_2', _ => nondep a_2 a_2'
|
||
else false
|
||
termination_by structural x
|
||
|
||
/--
|
||
info: theorem nondep.eq_def.{u_1, u_2} : ∀ {n : Nat} (x : I n) (x' : I n),
|
||
nondep x x' =
|
||
if h : P x then
|
||
match n, x, x', ⋯ with
|
||
| .(n + 1), a_2.cons, a_2'.cons, x => nondep a_2 a_2'
|
||
else false
|
||
-/
|
||
#guard_msgs in
|
||
#print sig nondep.eq_def
|