diff --git a/Mathlib/Data/Option/Basic.lean b/Mathlib/Data/Option/Basic.lean index 8e3a1d91e9adc..7e512393a8fcd 100644 --- a/Mathlib/Data/Option/Basic.lean +++ b/Mathlib/Data/Option/Basic.lean @@ -417,4 +417,14 @@ theorem elim_none_some (f : Option α → β) : (fun x ↦ Option.elim x (f none funext fun o ↦ by cases o <;> rfl #align option.elim_none_some Option.elim_none_some +theorem elim_comp (h : α → β) {f : γ → α} {x : α} {i : Option γ} : + (i.elim (h x) fun j => h (f j)) = h (i.elim x f) := by cases i <;> rfl + +theorem elim_comp₂ (h : α → β → γ) {f : γ → α} {x : α} {g : γ → β} {y : β} + {i : Option γ} : (i.elim (h x y) fun j => h (f j) (g j)) = h (i.elim x f) (i.elim y g) := by + cases i <;> rfl + +theorem elim_apply {f : γ → α → β} {x : α → β} {i : Option γ} {y : α} : + i.elim x f y = i.elim (x y) fun j => f j y := by rw [elim_comp fun f : α → β => f y] + end Option diff --git a/Mathlib/Data/Set/Prod.lean b/Mathlib/Data/Set/Prod.lean index af263da690ca5..3ac26b8847b1b 100644 --- a/Mathlib/Data/Set/Prod.lean +++ b/Mathlib/Data/Set/Prod.lean @@ -690,6 +690,11 @@ theorem pi_univ (s : Set ι) : (pi s fun i => (univ : Set (α i))) = univ := eq_univ_of_forall fun _ _ _ => mem_univ _ #align set.pi_univ Set.pi_univ +@[simp] +theorem pi_univ_ite (s : Set ι) [DecidablePred (· ∈ s)] (t : ∀ i, Set (α i)) : + (pi univ fun i => if i ∈ s then t i else univ) = s.pi t := by + ext; simp_rw [Set.mem_pi]; apply forall_congr'; intro i; split_ifs with h <;> simp [h] + theorem pi_mono (h : ∀ i ∈ s, t₁ i ⊆ t₂ i) : pi s t₁ ⊆ pi s t₂ := fun _ hx i hi => h i hi <| hx i hi #align set.pi_mono Set.pi_mono @@ -926,3 +931,37 @@ theorem univ_pi_ite (s : Set ι) [DecidablePred (· ∈ s)] (t : ∀ i, Set (α end Pi end Set + +namespace Equiv + +open Set +variable {ι ι' : Type*} {α : ι → Type*} + +theorem piCongrLeft_symm_preimage_pi (f : ι' ≃ ι) (s : Set ι') (t : ∀ i, Set (α i)) : + (f.piCongrLeft α).symm ⁻¹' s.pi (fun i' => t <| f i') = (f '' s).pi t := by + ext; simp + +theorem piCongrLeft_symm_preimage_univ_pi (f : ι' ≃ ι) (t : ∀ i, Set (α i)) : + (f.piCongrLeft α).symm ⁻¹' univ.pi (fun i' => t <| f i') = univ.pi t := by + simpa [f.surjective.range_eq] using piCongrLeft_symm_preimage_pi f univ t + +theorem piCongrLeft_preimage_pi (f : ι' ≃ ι) (s : Set ι') (t : ∀ i, Set (α i)) : + f.piCongrLeft α ⁻¹' (f '' s).pi t = s.pi fun i => t (f i) := by + apply Set.ext; + rw [← (f.piCongrLeft α).symm.forall_congr_left] + simp + +theorem piCongrLeft_preimage_univ_pi (f : ι' ≃ ι) (t : ∀ i, Set (α i)) : + f.piCongrLeft α ⁻¹' univ.pi t = univ.pi fun i => t (f i) := by + simpa [f.surjective.range_eq] using piCongrLeft_preimage_pi f univ t + +theorem sumPiEquivProdPi_symm_preimage_univ_pi (π : ι ⊕ ι' → Type _) (t : ∀ i, Set (π i)) : + (sumPiEquivProdPi π).symm ⁻¹' univ.pi t = + univ.pi (fun i => t (.inl i)) ×ˢ univ.pi fun i => t (.inr i) := by + ext + simp_rw [mem_preimage, mem_prod, mem_univ_pi, sumPiEquivProdPi_symm_apply] + constructor + · intro h; constructor <;> intro i <;> apply h + · rintro ⟨h₁, h₂⟩ (i|i) <;> simp <;> apply_assumption + +end Equiv diff --git a/Mathlib/Data/Sum/Basic.lean b/Mathlib/Data/Sum/Basic.lean index 0df66d25f02e6..5d3ce32aa1a4b 100644 --- a/Mathlib/Data/Sum/Basic.lean +++ b/Mathlib/Data/Sum/Basic.lean @@ -34,6 +34,10 @@ theorem inl_injective : Function.Injective (inl : α → Sum α β) := fun _ _ theorem inr_injective : Function.Injective (inr : β → Sum α β) := fun _ _ ↦ inr.inj #align sum.inr_injective Sum.inr_injective +theorem sum_rec_congr (P : α ⊕ β → Sort*) (f : ∀ i, P (inl i)) (g : ∀ i, P (inr i)) + {x y : α ⊕ β} (h : x = y) : + @Sum.rec _ _ _ f g x = cast (congr_arg P h.symm) (@Sum.rec _ _ _ f g y) := by cases h; rfl + section get #align sum.is_left Sum.isLeft diff --git a/Mathlib/Logic/Basic.lean b/Mathlib/Logic/Basic.lean index ae0a70b9fff61..a8133e683ce62 100644 --- a/Mathlib/Logic/Basic.lean +++ b/Mathlib/Logic/Basic.lean @@ -383,6 +383,10 @@ theorem imp_iff_or_not : b → a ↔ a ∨ ¬b := Decidable.imp_iff_or_not theorem not_imp_not : ¬a → ¬b ↔ b → a := Decidable.not_imp_not #align not_imp_not not_imp_not +@[simp] +theorem imp_and_neg_imp_iff (p q : Prop) : (p → q) ∧ (¬p → q) ↔ q := by + rw [imp_iff_or_not, imp_iff_or_not, not_not, ← or_and_left, not_and_self_iff, or_false_iff] + /-- Provide the reverse of modus tollens (`mt`) as dot notation for implications. -/ protected theorem Function.mtr : (¬a → ¬b) → b → a := not_imp_not.mp #align function.mtr Function.mtr @@ -563,6 +567,9 @@ theorem cast_eq_iff_heq : cast e a = a' ↔ HEq a a' := ⟨heq_of_cast_eq _, fun h ↦ by cases h; rfl⟩ #align cast_eq_iff_heq cast_eq_iff_heq +theorem Eq.rec_eq_cast {α : Sort _} {P : α → Sort _} {x y : α} (h : x = y) (z : P x) : + h ▸ z = cast (congr_arg P h) z := by induction h; rfl + --Porting note: new theorem. More general version of `eqRec_heq` theorem eqRec_heq' {α : Sort u_1} {a' : α} {motive : (a : α) → a' = a → Sort u} (p : motive a' (rfl : a' = a')) {a : α} (t : a' = a) : diff --git a/Mathlib/Logic/Equiv/Basic.lean b/Mathlib/Logic/Equiv/Basic.lean index 00c196c08f0ab..5e07b978e53c7 100644 --- a/Mathlib/Logic/Equiv/Basic.lean +++ b/Mathlib/Logic/Equiv/Basic.lean @@ -15,6 +15,7 @@ import Mathlib.Tactic.Lift import Mathlib.Tactic.Convert import Mathlib.Tactic.Contrapose import Mathlib.Tactic.GeneralizeProofs +import Mathlib.Tactic.SimpRw #align_import logic.equiv.basic from "leanprover-community/mathlib"@"cd391184c85986113f8c00844cfe6dda1d34be3d" @@ -918,6 +919,23 @@ def arrowProdEquivProdArrow (α β γ : Type*) : (γ → α × β) ≃ (γ → open Sum +/-- The type of dependent functions on a sum type `ι ⊕ ι'` is equivalent to the type of pairs of +functions on `ι` and on `ι'`. This is a dependent version of `Equiv.sumArrowEquivProdArrow`. -/ +@[simps] +def sumPiEquivProdPi (π : ι ⊕ ι' → Type _) : (∀ i, π i) ≃ (∀ i, π (inl i)) × ∀ i', π (inr i') + where + toFun f := ⟨fun i => f (inl i), fun i' => f (inr i')⟩ + invFun g := Sum.rec g.1 g.2 + left_inv f := by ext (i | i) <;> rfl + right_inv g := Prod.ext rfl rfl + +/-- The equivalence between a product of two dependent functions types and a single dependent +function type. Basically a symmetric version of `Equiv.sumPiEquivProdPi`. -/ +@[simps!] +def prodPiEquivSumPi (π : ι → Type _) (π' : ι' → Type _) : + ((∀ i, π i) × ∀ i', π' i') ≃ ∀ i, Sum.elim π π' i := + sumPiEquivProdPi (Sum.elim π π') |>.symm + /-- The type of functions on a sum type `α ⊕ β` is equivalent to the type of pairs of functions on `α` and on `β`. -/ def sumArrowEquivProdArrow (α β γ : Type*) : (Sum α β → γ) ≃ (α → γ) × (β → γ) := @@ -1175,6 +1193,12 @@ def subtypeEquivRight {p q : α → Prop} (e : ∀ x, p x ↔ q x) : { x // p x #align equiv.subtype_equiv_right_apply_coe Equiv.subtypeEquivRight_apply_coe #align equiv.subtype_equiv_right_symm_apply_coe Equiv.subtypeEquivRight_symm_apply_coe +lemma subtypeEquivRight_apply {p q : α → Prop} (e : ∀ x, p x ↔ q x) + (z : { x // p x }) : subtypeEquivRight e z = ⟨z, (e z.1).mp z.2⟩ := rfl + +lemma subtypeEquivRight_symm_apply {p q : α → Prop} (e : ∀ x, p x ↔ q x) + (z : { x // q x }) : (subtypeEquivRight e).symm z = ⟨z, (e z.1).mpr z.2⟩ := rfl + /-- If `α ≃ β`, then for any predicate `p : β → Prop` the subtype `{a // p (e a)}` is equivalent to the subtype `{b // p b}`. -/ def subtypeEquivOfSubtype {p : β → Prop} (e : α ≃ β) : { a : α // p (e a) } ≃ { b : β // p b } := @@ -1857,6 +1881,25 @@ lemma piCongrLeft_apply_apply (f : ∀ a, P (e a)) (a : α) : (piCongrLeft P e) f (e a) = f a := piCongrLeft'_symm_apply_apply P e.symm f a +open Sum + +lemma piCongrLeft_apply_eq_cast {P : β → Sort v} {e : α ≃ β} + (f : (a : α) → P (e a)) (b : β) : + piCongrLeft P e f b = cast (congr_arg P (e.apply_symm_apply b)) (f (e.symm b)) := + Eq.rec_eq_cast _ _ + +theorem piCongrLeft_sum_inl (π : ι'' → Type _) (e : ι ⊕ ι' ≃ ι'') (f : ∀ i, π (e (inl i))) + (g : ∀ i, π (e (inr i))) (i : ι) : + piCongrLeft π e (sumPiEquivProdPi (fun x => π (e x)) |>.symm (f, g)) (e (inl i)) = f i := by + simp_rw [piCongrLeft_apply_eq_cast, sumPiEquivProdPi_symm_apply, + sum_rec_congr _ _ _ (e.symm_apply_apply (inl i)), cast_cast, cast_eq] + +theorem piCongrLeft_sum_inr (π : ι'' → Type _) (e : ι ⊕ ι' ≃ ι'') (f : ∀ i, π (e (inl i))) + (g : ∀ i, π (e (inr i))) (j : ι') : + piCongrLeft π e (sumPiEquivProdPi (fun x => π (e x)) |>.symm (f, g)) (e (inr j)) = g j := by + simp_rw [piCongrLeft_apply_eq_cast, sumPiEquivProdPi_symm_apply, + sum_rec_congr _ _ _ (e.symm_apply_apply (inr j)), cast_cast, cast_eq] + end section