/-! A few tests for functional induction theorems generated from mutual recursive inductives. Some more tests are in `structuralMutual.lean` and `funind_structural`. -/ set_option guard_msgs.diff true inductive Tree (α : Type u) : Type u where | node : α → (Bool → List (Tree α)) → Tree α -- Recursion over nested inductive mutual def Tree.size : Tree α → Nat | .node _ tsf => 1 + size_aux (tsf true) + size_aux (tsf false) termination_by structural t => t def Tree.size_aux : List (Tree α) → Nat | [] => 0 | t :: ts => size t + size_aux ts end /-- info: Tree.size.induct.{u_1} {α : Type u_1} (motive_1 : Tree α → Prop) (motive_2 : List (Tree α) → Prop) (case1 : ∀ (a : α) (tsf : Bool → List (Tree α)), motive_2 (tsf true) → motive_2 (tsf false) → motive_1 (Tree.node a tsf)) (case2 : motive_2 []) (case3 : ∀ (t : Tree α) (ts : List (Tree α)), motive_1 t → motive_2 ts → motive_2 (t :: ts)) (a✝ : Tree α) : motive_1 a✝ -/ #guard_msgs in #check Tree.size.induct -- Recursion over nested inductive, functions in the “wrong” order (auxiliary first) mutual def Tree.size_aux' : List (Tree α) → Nat | [] => 0 | t :: ts => size' t + size_aux' ts def Tree.size' : Tree α → Nat | .node _ tsf => 1 + size_aux' (tsf true) + size_aux' (tsf false) termination_by structural t => t end /-- info: Tree.size_aux'.mutual_induct.{u_1} {α : Type u_1} (motive_1 : List (Tree α) → Prop) (motive_2 : Tree α → Prop) (case1 : ∀ (a : α) (tsf : Bool → List (Tree α)), motive_1 (tsf true) → motive_1 (tsf false) → motive_2 (Tree.node a tsf)) (case2 : motive_1 []) (case3 : ∀ (t : Tree α) (ts : List (Tree α)), motive_2 t → motive_1 ts → motive_1 (t :: ts)) : (∀ (a : List (Tree α)), motive_1 a) ∧ ∀ (a : Tree α), motive_2 a -/ #guard_msgs in #check Tree.size_aux'.mutual_induct -- Similar, but with many packed functions mutual def Tree.size_aux1 : List (Tree α) → Nat | [] => 0 | t :: ts => size2 t + size_aux2 ts def Tree.size1 : Tree α → Nat | .node _ tsf => 1 + size_aux2 (tsf true) + size_aux3 (tsf false) termination_by structural t => t def Tree.size_aux2 : List (Tree α) → Nat | [] => 0 | t :: ts => size3 t + size_aux3 ts def Tree.size2 : Tree α → Nat | .node _ tsf => 1 + size_aux3 (tsf true) + size_aux1 (tsf false) def Tree.size_aux3 : List (Tree α) → Nat | [] => 0 | t :: ts => size1 t + size_aux1 ts def Tree.size3 : Tree α → Nat | .node _ tsf => 1 + size_aux1 (tsf true) + size_aux2 (tsf false) end /-- info: Tree.size_aux1.mutual_induct.{u_1} {α : Type u_1} (motive_1 motive_2 motive_3 : List (Tree α) → Prop) (motive_4 motive_5 motive_6 : Tree α → Prop) (case1 : ∀ (a : α) (tsf : Bool → List (Tree α)), motive_2 (tsf true) → motive_3 (tsf false) → motive_4 (Tree.node a tsf)) (case2 : ∀ (a : α) (tsf : Bool → List (Tree α)), motive_1 (tsf true) → motive_2 (tsf false) → motive_5 (Tree.node a tsf)) (case3 : ∀ (a : α) (tsf : Bool → List (Tree α)), motive_3 (tsf true) → motive_1 (tsf false) → motive_6 (Tree.node a tsf)) (case4 : motive_1 []) (case5 : ∀ (t : Tree α) (ts : List (Tree α)), motive_6 t → motive_2 ts → motive_1 (t :: ts)) (case6 : motive_2 []) (case7 : ∀ (t : Tree α) (ts : List (Tree α)), motive_5 t → motive_3 ts → motive_2 (t :: ts)) (case8 : motive_3 []) (case9 : ∀ (t : Tree α) (ts : List (Tree α)), motive_4 t → motive_1 ts → motive_3 (t :: ts)) : (∀ (a : List (Tree α)), motive_1 a) ∧ (∀ (a : List (Tree α)), motive_2 a) ∧ (∀ (a : List (Tree α)), motive_3 a) ∧ (∀ (a : Tree α), motive_4 a) ∧ (∀ (a : Tree α), motive_5 a) ∧ ∀ (a : Tree α), motive_6 a -/ #guard_msgs in #check Tree.size_aux1.mutual_induct namespace Map2 mutual def map2a (f : Nat → Nat → Bool) : List Nat → List Nat → List Bool | x::xs, y::ys => f x y::map2b f xs ys | _, _ => [] termination_by structural x => x def map2b (f : Nat → Nat → Bool) : List Nat → List Nat → List Bool | x::xs, y::ys => f x y::map2a f xs ys | _, _ => [] termination_by structural x => x end /-- info: Map2.map2a.mutual_induct (motive_1 motive_2 : List Nat → List Nat → Prop) (case1 : ∀ (x : Nat) (xs : List Nat) (y : Nat) (ys : List Nat), motive_2 xs ys → motive_1 (x :: xs) (y :: ys)) (case2 : ∀ (t x : List Nat), (∀ (x_1 : Nat) (xs : List Nat) (y : Nat) (ys : List Nat), t = x_1 :: xs → x = y :: ys → False) → motive_1 t x) (case3 : ∀ (x : Nat) (xs : List Nat) (y : Nat) (ys : List Nat), motive_1 xs ys → motive_2 (x :: xs) (y :: ys)) (case4 : ∀ (t x : List Nat), (∀ (x_1 : Nat) (xs : List Nat) (y : Nat) (ys : List Nat), t = x_1 :: xs → x = y :: ys → False) → motive_2 t x) : (∀ (a a_1 : List Nat), motive_1 a a_1) ∧ ∀ (a a_1 : List Nat), motive_2 a a_1 -/ #guard_msgs in #check map2a.mutual_induct /-- info: Map2.map2a.induct (motive_1 motive_2 : List Nat → List Nat → Prop) (case1 : ∀ (x : Nat) (xs : List Nat) (y : Nat) (ys : List Nat), motive_2 xs ys → motive_1 (x :: xs) (y :: ys)) (case2 : ∀ (t x : List Nat), (∀ (x_1 : Nat) (xs : List Nat) (y : Nat) (ys : List Nat), t = x_1 :: xs → x = y :: ys → False) → motive_1 t x) (case3 : ∀ (x : Nat) (xs : List Nat) (y : Nat) (ys : List Nat), motive_1 xs ys → motive_2 (x :: xs) (y :: ys)) (case4 : ∀ (t x : List Nat), (∀ (x_1 : Nat) (xs : List Nat) (y : Nat) (ys : List Nat), t = x_1 :: xs → x = y :: ys → False) → motive_2 t x) (a✝ a✝¹ : List Nat) : motive_1 a✝ a✝¹ -/ #guard_msgs in #check map2a.induct end Map2