Skip to content

Commit 65590a2

Browse files
committed
refactor(Data/List/Induction): improve definition of reverseRecOn (leanprover-community#33192)
This PR improves the definition of `List.reverseRecOn`.
1 parent 330e666 commit 65590a2

1 file changed

Lines changed: 32 additions & 27 deletions

File tree

Mathlib/Data/List/Induction.lean

Lines changed: 32 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -19,32 +19,39 @@ namespace List
1919
for `l ++ [a]` if it holds for `l`, then it holds for all lists. The principle is given for
2020
a `Sort`-valued predicate, i.e., it can also be used to construct data. -/
2121
@[elab_as_elim]
22-
def reverseRecOn {motive : List α → Sort*} (l : List α) (nil : motive [])
23-
(append_singleton : ∀ (l : List α) (a : α), motive l → motive (l ++ [a])) : motive l :=
24-
match h : reverse l with
25-
| [] => cast (congr_arg motive <| by simpa using congr(reverse $h.symm)) <|
26-
nil
27-
| head :: tail =>
28-
cast (congr_arg motive <| by simpa using congr(reverse $h.symm)) <|
29-
append_singleton _ head <| reverseRecOn (reverse tail) nil append_singleton
30-
termination_by l.length
31-
decreasing_by
32-
simp_wf
33-
rw [← length_reverse (as := l), h, length_cons]
34-
simp
22+
def reverseRec {motive : List α → Sort*} (nil : motive [])
23+
(append_singleton : ∀ (l : List α) (a : α), motive l → motive (l ++ [a])) : ∀ l, motive l
24+
| [] => nil
25+
| a :: l => (dropLast_concat_getLast (cons_ne_nil a l)) ▸
26+
append_singleton _ _ ((a :: l).dropLast.reverseRec nil append_singleton)
27+
termination_by l => l.length
28+
29+
@[simp]
30+
theorem reverseRec_nil {motive : List α → Sort*} (nil : motive [])
31+
(append_singleton : ∀ (l : List α) (a : α), motive l → motive (l ++ [a])) :
32+
[].reverseRec nil append_singleton = nil := by grind [reverseRec]
3533

3634
@[simp]
35+
theorem reverseRec_concat {motive : List α → Sort*} (x : α) (xs : List α) (nil : motive [])
36+
(append_singleton : ∀ (l : List α) (a : α), motive l → motive (l ++ [a])) :
37+
(xs ++ [x]).reverseRec nil append_singleton =
38+
append_singleton xs x (xs.reverseRec nil append_singleton) := by
39+
grind [reverseRec, cases List]
40+
41+
/-- Like `reverseRec`, but with the list parameter placed first. -/
42+
@[elab_as_elim]
43+
abbrev reverseRecOn {motive : List α → Sort*} (l : List α) (nil : motive [])
44+
(append_singleton : ∀ (l : List α) (a : α), motive l → motive (l ++ [a])) : motive l :=
45+
reverseRec nil append_singleton l
46+
3747
theorem reverseRecOn_nil {motive : List α → Sort*} (nil : motive [])
3848
(append_singleton : ∀ (l : List α) (a : α), motive l → motive (l ++ [a])) :
39-
reverseRecOn [] nil append_singleton = nil := reverseRecOn.eq_1 ..
49+
reverseRecOn [] nil append_singleton = nil := by simp
4050

41-
-- `unusedHavesSuffices` is getting confused by the unfolding of `reverseRecOn`
42-
@[simp, nolint unusedHavesSuffices]
4351
theorem reverseRecOn_concat {motive : List α → Sort*} (x : α) (xs : List α) (nil : motive [])
4452
(append_singleton : ∀ (l : List α) (a : α), motive l → motive (l ++ [a])) :
45-
reverseRecOn (motive := motive) (xs ++ [x]) nil append_singleton =
46-
append_singleton _ _ (reverseRecOn (motive := motive) xs nil append_singleton) := by
47-
grind [reverseRecOn]
53+
(xs ++ [x]).reverseRecOn nil append_singleton =
54+
append_singleton xs x (reverseRecOn xs nil append_singleton) := by simp
4855

4956
/-- Bidirectional induction principle for lists: if a property holds for the empty list, the
5057
singleton list, and `a :: (l ++ [b])` from `l`, then it holds for all lists. This can be used to
@@ -57,25 +64,24 @@ def bidirectionalRec {motive : List α → Sort*} (nil : motive []) (singleton :
5764
| [] => nil
5865
| [a] => singleton a
5966
| a :: b :: l =>
60-
let l' := dropLast (b :: l)
61-
let b' := getLast (b :: l) (cons_ne_nil _ _)
62-
cast (by rw [← dropLast_append_getLast (cons_ne_nil b l)]) <|
63-
cons_append a l' b' (bidirectionalRec nil singleton cons_append l')
67+
(dropLast_concat_getLast (cons_ne_nil b l)) ▸
68+
cons_append a ((b :: l).dropLast) ((b :: l).getLast (cons_ne_nil _ _))
69+
((b :: l).dropLast.bidirectionalRec nil singleton cons_append)
6470
termination_by l => l.length
6571

6672
@[simp]
6773
theorem bidirectionalRec_nil {motive : List α → Sort*}
6874
(nil : motive []) (singleton : ∀ a : α, motive [a])
6975
(cons_append : ∀ (a : α) (l : List α) (b : α), motive l → motive (a :: (l ++ [b]))) :
70-
bidirectionalRec nil singleton cons_append [] = nil := bidirectionalRec.eq_1 ..
76+
bidirectionalRec nil singleton cons_append [] = nil := by grind [bidirectionalRec]
7177

7278

7379
@[simp]
7480
theorem bidirectionalRec_singleton {motive : List α → Sort*}
7581
(nil : motive []) (singleton : ∀ a : α, motive [a])
7682
(cons_append : ∀ (a : α) (l : List α) (b : α), motive l → motive (a :: (l ++ [b]))) (a : α) :
7783
bidirectionalRec nil singleton cons_append [a] = singleton a := by
78-
simp [bidirectionalRec]
84+
grind [bidirectionalRec]
7985

8086
@[simp]
8187
theorem bidirectionalRec_cons_append {motive : List α → Sort*}
@@ -84,8 +90,7 @@ theorem bidirectionalRec_cons_append {motive : List α → Sort*}
8490
(a : α) (l : List α) (b : α) :
8591
bidirectionalRec nil singleton cons_append (a :: (l ++ [b])) =
8692
cons_append a l b (bidirectionalRec nil singleton cons_append l) := by
87-
conv_lhs => unfold bidirectionalRec
88-
cases l with grind
93+
grind [bidirectionalRec, cases List]
8994

9095
/-- Like `bidirectionalRec`, but with the list parameter placed first. -/
9196
@[elab_as_elim]

0 commit comments

Comments
 (0)