diff --git a/src/Init/Core.lean b/src/Init/Core.lean index 91e7409177..89d801ec98 100644 --- a/src/Init/Core.lean +++ b/src/Init/Core.lean @@ -2040,4 +2040,8 @@ class LawfulCommIdentity (op : α → α → α) (o : outParam α) [hc : Commuta left_id a := Eq.trans (hc.comm o a) (right_id a) right_id a := Eq.trans (hc.comm a o) (left_id a) +instance : Commutative Or := ⟨fun _ _ => propext or_comm⟩ +instance : Commutative And := ⟨fun _ _ => propext and_comm⟩ +instance : Commutative Iff := ⟨fun _ _ => propext iff_comm⟩ + end Std diff --git a/src/Init/Data/BitVec/Lemmas.lean b/src/Init/Data/BitVec/Lemmas.lean index fb3d87dc84..2394aaddc3 100644 --- a/src/Init/Data/BitVec/Lemmas.lean +++ b/src/Init/Data/BitVec/Lemmas.lean @@ -826,13 +826,18 @@ theorem ofNat_add_ofNat {n} (x y : Nat) : x#n + y#n = (x + y)#n := protected theorem add_assoc (x y z : BitVec n) : x + y + z = x + (y + z) := by apply eq_of_toNat_eq ; simp [Nat.add_assoc] +instance : Std.Associative (α := BitVec n) (· + ·) := ⟨BitVec.add_assoc⟩ protected theorem add_comm (x y : BitVec n) : x + y = y + x := by simp [add_def, Nat.add_comm] +instance : Std.Commutative (α := BitVec n) (· + ·) := ⟨BitVec.add_comm⟩ @[simp] protected theorem add_zero (x : BitVec n) : x + 0#n = x := by simp [add_def] @[simp] protected theorem zero_add (x : BitVec n) : 0#n + x = x := by simp [add_def] +instance : Std.LawfulIdentity (α := BitVec n) (· + ·) 0#n where + left_id := BitVec.zero_add + right_id := BitVec.add_zero theorem truncate_add (x y : BitVec w) (h : i ≤ w) : (x + y).truncate i = x.truncate i + y.truncate i := by diff --git a/src/Init/Data/Bool.lean b/src/Init/Data/Bool.lean index 83539c2760..042d8e1e02 100644 --- a/src/Init/Data/Bool.lean +++ b/src/Init/Data/Bool.lean @@ -74,6 +74,7 @@ Added for confluence with `not_and_self` `and_not_self` on term @[simp] theorem eq_false_and_eq_true_self : ∀(b : Bool), (b = false ∧ b = true) ↔ False := by decide theorem and_comm : ∀ (x y : Bool), (x && y) = (y && x) := by decide +instance : Std.Commutative (· && ·) := ⟨and_comm⟩ theorem and_left_comm : ∀ (x y z : Bool), (x && (y && z)) = (y && (x && z)) := by decide theorem and_right_comm : ∀ (x y z : Bool), ((x && y) && z) = ((x && z) && y) := by decide @@ -120,6 +121,7 @@ Needed for confluence of term `(a || b) ↔ a` which reduces to `(a || b) = a` v @[simp] theorem iff_or_self : ∀(a b : Bool), (b = (a || b)) ↔ (a → b) := by decide theorem or_comm : ∀ (x y : Bool), (x || y) = (y || x) := by decide +instance : Std.Commutative (· || ·) := ⟨or_comm⟩ theorem or_left_comm : ∀ (x y z : Bool), (x || (y || z)) = (y || (x || z)) := by decide theorem or_right_comm : ∀ (x y z : Bool), ((x || y) || z) = ((x || z) || y) := by decide @@ -186,12 +188,18 @@ in false_eq and true_eq. @[simp] theorem true_beq : ∀b, (true == b) = b := by decide @[simp] theorem false_beq : ∀b, (false == b) = !b := by decide @[simp] theorem beq_true : ∀b, (b == true) = b := by decide +instance : Std.LawfulIdentity (· == ·) true where + left_id := true_beq + right_id := beq_true @[simp] theorem beq_false : ∀b, (b == false) = !b := by decide @[simp] theorem true_bne : ∀(b : Bool), (true != b) = !b := by decide @[simp] theorem false_bne : ∀(b : Bool), (false != b) = b := by decide @[simp] theorem bne_true : ∀(b : Bool), (b != true) = !b := by decide @[simp] theorem bne_false : ∀(b : Bool), (b != false) = b := by decide +instance : Std.LawfulIdentity (· != ·) false where + left_id := false_bne + right_id := bne_false @[simp] theorem not_beq_self : ∀ (x : Bool), ((!x) == x) = false := by decide @[simp] theorem beq_not_self : ∀ (x : Bool), (x == !x) = false := by decide @@ -214,6 +222,7 @@ due to `beq_iff_eq`. @[simp] theorem not_bne_not : ∀ (x y : Bool), ((!x) != (!y)) = (x != y) := by decide @[simp] theorem bne_assoc : ∀ (x y z : Bool), ((x != y) != z) = (x != (y != z)) := by decide +instance : Std.Associative (· != ·) := ⟨bne_assoc⟩ @[simp] theorem bne_left_inj : ∀ (x y z : Bool), (x != y) = (x != z) ↔ y = z := by decide @[simp] theorem bne_right_inj : ∀ (x y z : Bool), (x != z) = (y != z) ↔ x = y := by decide diff --git a/src/Init/Data/Fin/Lemmas.lean b/src/Init/Data/Fin/Lemmas.lean index a61ce35bfa..6b09f91d23 100644 --- a/src/Init/Data/Fin/Lemmas.lean +++ b/src/Init/Data/Fin/Lemmas.lean @@ -793,15 +793,20 @@ protected theorem mul_one (k : Fin (n + 1)) : k * 1 = k := by protected theorem mul_comm (a b : Fin n) : a * b = b * a := ext <| by rw [mul_def, mul_def, Nat.mul_comm] +instance : Std.Commutative (α := Fin n) (· * ·) := ⟨Fin.mul_comm⟩ protected theorem mul_assoc (a b c : Fin n) : a * b * c = a * (b * c) := by apply eq_of_val_eq simp only [val_mul] rw [← Nat.mod_eq_of_lt a.isLt, ← Nat.mod_eq_of_lt b.isLt, ← Nat.mod_eq_of_lt c.isLt] simp only [← Nat.mul_mod, Nat.mul_assoc] +instance : Std.Associative (α := Fin n) (· * ·) := ⟨Fin.mul_assoc⟩ protected theorem one_mul (k : Fin (n + 1)) : (1 : Fin (n + 1)) * k = k := by rw [Fin.mul_comm, Fin.mul_one] +instance : Std.LawfulIdentity (α := Fin (n + 1)) (· * ·) 1 where + left_id := Fin.one_mul + right_id := Fin.mul_one protected theorem mul_zero (k : Fin (n + 1)) : k * 0 = 0 := by simp [ext_iff, mul_def] diff --git a/src/Init/Data/Int/Lemmas.lean b/src/Init/Data/Int/Lemmas.lean index f23dc2bcc6..6012107292 100644 --- a/src/Init/Data/Int/Lemmas.lean +++ b/src/Init/Data/Int/Lemmas.lean @@ -137,12 +137,16 @@ protected theorem add_comm : ∀ a b : Int, a + b = b + a | ofNat _, -[_+1] => rfl | -[_+1], ofNat _ => rfl | -[_+1], -[_+1] => by simp [Nat.add_comm] +instance : Std.Commutative (α := Int) (· + ·) := ⟨Int.add_comm⟩ @[simp] protected theorem add_zero : ∀ a : Int, a + 0 = a | ofNat _ => rfl | -[_+1] => rfl @[simp] protected theorem zero_add (a : Int) : 0 + a = a := Int.add_comm .. ▸ a.add_zero +instance : Std.LawfulIdentity (α := Int) (· + ·) 0 where + left_id := Int.zero_add + right_id := Int.add_zero theorem ofNat_add_negSucc_of_lt (h : m < n.succ) : ofNat m + -[n+1] = -[n - m+1] := show subNatNat .. = _ by simp [succ_sub (le_of_lt_succ h), subNatNat] @@ -196,6 +200,7 @@ where simp rw [Int.add_comm, subNatNat_add_negSucc] simp [Nat.add_comm, Nat.add_left_comm, Nat.add_assoc] +instance : Std.Associative (α := Int) (· + ·) := ⟨Int.add_assoc⟩ protected theorem add_left_comm (a b c : Int) : a + (b + c) = b + (a + c) := by rw [← Int.add_assoc, Int.add_comm a, Int.add_assoc] @@ -351,6 +356,7 @@ protected theorem sub_right_inj (i j k : Int) : (i - k = j - k) ↔ i = j := by protected theorem mul_comm (a b : Int) : a * b = b * a := by cases a <;> cases b <;> simp [Nat.mul_comm] +instance : Std.Commutative (α := Int) (· * ·) := ⟨Int.mul_comm⟩ theorem ofNat_mul_negOfNat (m n : Nat) : (m : Nat) * negOfNat n = negOfNat (m * n) := by cases n <;> rfl @@ -369,6 +375,7 @@ attribute [local simp] ofNat_mul_negOfNat negOfNat_mul_ofNat protected theorem mul_assoc (a b c : Int) : a * b * c = a * (b * c) := by cases a <;> cases b <;> cases c <;> simp [Nat.mul_assoc] +instance : Std.Associative (α := Int) (· * ·) := ⟨Int.mul_assoc⟩ protected theorem mul_left_comm (a b c : Int) : a * (b * c) = b * (a * c) := by rw [← Int.mul_assoc, ← Int.mul_assoc, Int.mul_comm a] @@ -458,6 +465,9 @@ protected theorem sub_mul (a b c : Int) : (a - b) * c = a * c - b * c := by | -[n+1] => show -[1 * n +1] = -[n+1] by rw [Nat.one_mul] @[simp] protected theorem mul_one (a : Int) : a * 1 = a := by rw [Int.mul_comm, Int.one_mul] +instance : Std.LawfulIdentity (α := Int) (· * ·) 1 where + left_id := Int.one_mul + right_id := Int.mul_one protected theorem mul_neg_one (a : Int) : a * -1 = -a := by rw [Int.mul_neg, Int.mul_one] diff --git a/src/Init/Data/Int/Order.lean b/src/Init/Data/Int/Order.lean index ca734d3fda..b3510b2db2 100644 --- a/src/Init/Data/Int/Order.lean +++ b/src/Init/Data/Int/Order.lean @@ -187,6 +187,7 @@ protected theorem min_comm (a b : Int) : min a b = min b a := by by_cases h₁ : a ≤ b <;> by_cases h₂ : b ≤ a <;> simp [h₁, h₂] · exact Int.le_antisymm h₁ h₂ · cases not_or_intro h₁ h₂ <| Int.le_total .. +instance : Std.Commutative (α := Int) min := ⟨Int.min_comm⟩ protected theorem min_le_right (a b : Int) : min a b ≤ b := by rw [Int.min_def]; split <;> simp [*] @@ -206,6 +207,7 @@ protected theorem max_comm (a b : Int) : max a b = max b a := by by_cases h₁ : a ≤ b <;> by_cases h₂ : b ≤ a <;> simp [h₁, h₂] · exact Int.le_antisymm h₂ h₁ · cases not_or_intro h₁ h₂ <| Int.le_total .. +instance : Std.Commutative (α := Int) max := ⟨Int.max_comm⟩ protected theorem le_max_left (a b : Int) : a ≤ max a b := by rw [Int.max_def]; split <;> simp [*] diff --git a/src/Init/Data/List/Basic.lean b/src/Init/Data/List/Basic.lean index 467e860c03..3d76f07d97 100644 --- a/src/Init/Data/List/Basic.lean +++ b/src/Init/Data/List/Basic.lean @@ -127,6 +127,9 @@ instance : Append (List α) := ⟨List.append⟩ | nil => rfl | cons a as ih => simp_all [HAppend.hAppend, Append.append, List.append] +instance : Std.LawfulIdentity (α := List α) (· ++ ·) [] where + left_id := nil_append + right_id := append_nil @[simp] theorem cons_append (a : α) (as bs : List α) : (a::as) ++ bs = a::(as ++ bs) := rfl @@ -136,6 +139,7 @@ theorem append_assoc (as bs cs : List α) : (as ++ bs) ++ cs = as ++ (bs ++ cs) induction as with | nil => rfl | cons a as ih => simp [ih] +instance : Std.Associative (α := List α) (· ++ ·) := ⟨append_assoc⟩ theorem append_cons (as : List α) (b : α) (bs : List α) : as ++ b :: bs = as ++ [b] ++ bs := by induction as with diff --git a/src/Init/Data/Nat/Basic.lean b/src/Init/Data/Nat/Basic.lean index 9ecc1628c6..a4aa2ecbc8 100644 --- a/src/Init/Data/Nat/Basic.lean +++ b/src/Init/Data/Nat/Basic.lean @@ -137,6 +137,9 @@ instance : LawfulBEq Nat where @[simp] protected theorem zero_add : ∀ (n : Nat), 0 + n = n | 0 => rfl | n+1 => congrArg succ (Nat.zero_add n) +instance : Std.LawfulIdentity (α := Nat) (· + ·) 0 where + left_id := Nat.zero_add + right_id := Nat.add_zero theorem succ_add : ∀ (n m : Nat), (succ n) + m = succ (n + m) | _, 0 => rfl @@ -160,10 +163,12 @@ protected theorem add_comm : ∀ (n m : Nat), n + m = m + n have : succ (n + m) = succ (m + n) := by apply congrArg; apply Nat.add_comm rw [succ_add m n] apply this +instance : Std.Commutative (α := Nat) (· + ·) := ⟨Nat.add_comm⟩ protected theorem add_assoc : ∀ (n m k : Nat), (n + m) + k = n + (m + k) | _, _, 0 => rfl | n, m, succ k => congrArg succ (Nat.add_assoc n m k) +instance : Std.Associative (α := Nat) (· + ·) := ⟨Nat.add_assoc⟩ protected theorem add_left_comm (n m k : Nat) : n + (m + k) = m + (n + k) := by rw [← Nat.add_assoc, Nat.add_comm n m, Nat.add_assoc] @@ -207,12 +212,16 @@ theorem succ_mul (n m : Nat) : (succ n) * m = (n * m) + m := by protected theorem mul_comm : ∀ (n m : Nat), n * m = m * n | n, 0 => (Nat.zero_mul n).symm ▸ (Nat.mul_zero n).symm ▸ rfl | n, succ m => (mul_succ n m).symm ▸ (succ_mul m n).symm ▸ (Nat.mul_comm n m).symm ▸ rfl +instance : Std.Commutative (α := Nat) (· * ·) := ⟨Nat.mul_comm⟩ @[simp] protected theorem mul_one : ∀ (n : Nat), n * 1 = n := Nat.zero_add @[simp] protected theorem one_mul (n : Nat) : 1 * n = n := Nat.mul_comm n 1 ▸ Nat.mul_one n +instance : Std.LawfulIdentity (α := Nat) (· * ·) 1 where + left_id := Nat.one_mul + right_id := Nat.mul_one protected theorem left_distrib (n m k : Nat) : n * (m + k) = n * m + n * k := by induction n with @@ -231,6 +240,7 @@ protected theorem add_mul (n m k : Nat) : (n + m) * k = n * k + m * k := protected theorem mul_assoc : ∀ (n m k : Nat), (n * m) * k = n * (m * k) | n, m, 0 => rfl | n, m, succ k => by simp [mul_succ, Nat.mul_assoc n m k, Nat.left_distrib] +instance : Std.Associative (α := Nat) (· * ·) := ⟨Nat.mul_assoc⟩ protected theorem mul_left_comm (n m k : Nat) : n * (m * k) = m * (n * k) := by rw [← Nat.mul_assoc, Nat.mul_comm n m, Nat.mul_assoc] diff --git a/src/Init/Data/Nat/Gcd.lean b/src/Init/Data/Nat/Gcd.lean index 37db257b49..c5a633e586 100644 --- a/src/Init/Data/Nat/Gcd.lean +++ b/src/Init/Data/Nat/Gcd.lean @@ -54,9 +54,13 @@ theorem gcd_succ (x y : Nat) : gcd (succ x) y = gcd (y % succ x) (succ x) := -- `simp [gcd_succ]` produces an invalid term unless `gcd_succ` is proved with `id rfl` instead rw [gcd_succ] exact gcd_zero_left _ +instance : Std.LawfulIdentity gcd 0 where + left_id := gcd_zero_left + right_id := gcd_zero_right @[simp] theorem gcd_self (n : Nat) : gcd n n = n := by cases n <;> simp [gcd_succ] +instance : Std.IdempotentOp gcd := ⟨gcd_self⟩ theorem gcd_rec (m n : Nat) : gcd m n = gcd (n % m) m := match m with @@ -97,6 +101,7 @@ theorem gcd_comm (m n : Nat) : gcd m n = gcd n m := Nat.dvd_antisymm (dvd_gcd (gcd_dvd_right m n) (gcd_dvd_left m n)) (dvd_gcd (gcd_dvd_right n m) (gcd_dvd_left n m)) +instance : Std.Commutative gcd := ⟨gcd_comm⟩ theorem gcd_eq_left_iff_dvd : m ∣ n ↔ gcd m n = m := ⟨fun h => by rw [gcd_rec, mod_eq_zero_of_dvd h, gcd_zero_left], diff --git a/src/Init/Data/Nat/Lcm.lean b/src/Init/Data/Nat/Lcm.lean index 4573c26d6d..cd86b5c670 100644 --- a/src/Init/Data/Nat/Lcm.lean +++ b/src/Init/Data/Nat/Lcm.lean @@ -14,6 +14,7 @@ def lcm (m n : Nat) : Nat := m * n / gcd m n theorem lcm_comm (m n : Nat) : lcm m n = lcm n m := by rw [lcm, lcm, Nat.mul_comm n m, gcd_comm n m] +instance : Std.Commutative lcm := ⟨lcm_comm⟩ @[simp] theorem lcm_zero_left (m : Nat) : lcm 0 m = 0 := by simp [lcm] @@ -22,11 +23,15 @@ theorem lcm_comm (m n : Nat) : lcm m n = lcm n m := by @[simp] theorem lcm_one_left (m : Nat) : lcm 1 m = m := by simp [lcm] @[simp] theorem lcm_one_right (m : Nat) : lcm m 1 = m := by simp [lcm] +instance : Std.LawfulIdentity lcm 1 where + left_id := lcm_one_left + right_id := lcm_one_right @[simp] theorem lcm_self (m : Nat) : lcm m m = m := by match eq_zero_or_pos m with | .inl h => rw [h, lcm_zero_left] | .inr h => simp [lcm, Nat.mul_div_cancel _ h] +instance : Std.IdempotentOp lcm := ⟨lcm_self⟩ theorem dvd_lcm_left (m n : Nat) : m ∣ lcm m n := ⟨n / gcd m n, by rw [← Nat.mul_div_assoc m (Nat.gcd_dvd_right m n)]; rfl⟩ @@ -54,6 +59,7 @@ Nat.dvd_antisymm (Nat.dvd_trans (dvd_lcm_left m n) (dvd_lcm_left (lcm m n) k)) (lcm_dvd (Nat.dvd_trans (dvd_lcm_right m n) (dvd_lcm_left (lcm m n) k)) (dvd_lcm_right (lcm m n) k))) +instance : Std.Associative lcm := ⟨lcm_assoc⟩ theorem lcm_ne_zero (hm : m ≠ 0) (hn : n ≠ 0) : lcm m n ≠ 0 := by intro h diff --git a/src/Init/Data/Nat/Lemmas.lean b/src/Init/Data/Nat/Lemmas.lean index 986e598db5..50124336f2 100644 --- a/src/Init/Data/Nat/Lemmas.lean +++ b/src/Init/Data/Nat/Lemmas.lean @@ -200,6 +200,7 @@ theorem succ_min_succ (x y) : min (succ x) (succ y) = succ (min x y) := by | inr h => rw [Nat.min_eq_right h, Nat.min_eq_right (Nat.succ_le_succ h)] @[simp] protected theorem min_self (a : Nat) : min a a = a := Nat.min_eq_left (Nat.le_refl _) +instance : Std.IdempotentOp (α := Nat) min := ⟨Nat.min_self⟩ @[simp] protected theorem zero_min (a) : min 0 a = 0 := Nat.min_eq_left (Nat.zero_le _) @@ -210,6 +211,7 @@ protected theorem min_assoc : ∀ (a b c : Nat), min (min a b) c = min a (min b | _, 0, _ => by rw [Nat.zero_min, Nat.min_zero, Nat.zero_min] | _, _, 0 => by rw [Nat.min_zero, Nat.min_zero, Nat.min_zero] | _+1, _+1, _+1 => by simp only [Nat.succ_min_succ]; exact congrArg succ <| Nat.min_assoc .. +instance : Std.Associative (α := Nat) min := ⟨Nat.min_assoc⟩ protected theorem sub_sub_eq_min : ∀ (a b : Nat), a - (a - b) = min a b | 0, _ => by rw [Nat.zero_sub, Nat.zero_min] @@ -249,16 +251,21 @@ protected theorem max_lt {a b c : Nat} : max a b < c ↔ a < c ∧ b < c := by rw [← Nat.succ_le, ← Nat.succ_max_succ a b]; exact Nat.max_le @[simp] protected theorem max_self (a : Nat) : max a a = a := Nat.max_eq_right (Nat.le_refl _) +instance : Std.IdempotentOp (α := Nat) max := ⟨Nat.max_self⟩ @[simp] protected theorem zero_max (a) : max 0 a = a := Nat.max_eq_right (Nat.zero_le _) @[simp] protected theorem max_zero (a) : max a 0 = a := Nat.max_eq_left (Nat.zero_le _) +instance : Std.LawfulIdentity (α := Nat) max 0 where + left_id := Nat.zero_max + right_id := Nat.max_zero protected theorem max_assoc : ∀ (a b c : Nat), max (max a b) c = max a (max b c) | 0, _, _ => by rw [Nat.zero_max, Nat.zero_max] | _, 0, _ => by rw [Nat.zero_max, Nat.max_zero] | _, _, 0 => by rw [Nat.max_zero, Nat.max_zero] | _+1, _+1, _+1 => by simp only [Nat.succ_max_succ]; exact congrArg succ <| Nat.max_assoc .. +instance : Std.Associative (α := Nat) max := ⟨Nat.max_assoc⟩ protected theorem sub_add_eq_max (a b : Nat) : a - b + b = max a b := by match Nat.le_total a b with diff --git a/src/Init/Data/Nat/MinMax.lean b/src/Init/Data/Nat/MinMax.lean index bc80a0db51..c9fc925eae 100644 --- a/src/Init/Data/Nat/MinMax.lean +++ b/src/Init/Data/Nat/MinMax.lean @@ -17,6 +17,7 @@ protected theorem min_comm (a b : Nat) : min a b = min b a := by | .inl h => simp [Nat.min_def, h, Nat.le_of_lt, Nat.not_le_of_lt] | .inr (.inl h) => simp [Nat.min_def, h] | .inr (.inr h) => simp [Nat.min_def, h, Nat.le_of_lt, Nat.not_le_of_lt] +instance : Std.Commutative (α := Nat) min := ⟨Nat.min_comm⟩ protected theorem min_le_right (a b : Nat) : min a b ≤ b := by by_cases (a <= b) <;> simp [Nat.min_def, *] @@ -47,6 +48,7 @@ protected theorem max_comm (a b : Nat) : max a b = max b a := by by_cases h₁ : a ≤ b <;> by_cases h₂ : b ≤ a <;> simp [h₁, h₂] · exact Nat.le_antisymm h₂ h₁ · cases not_or_intro h₁ h₂ <| Nat.le_total .. +instance : Std.Commutative (α := Nat) max := ⟨Nat.max_comm⟩ protected theorem le_max_left ( a b : Nat) : a ≤ max a b := by by_cases (a <= b) <;> simp [Nat.max_def, *] diff --git a/src/Init/SimpLemmas.lean b/src/Init/SimpLemmas.lean index 852bfb7a09..c72354b239 100644 --- a/src/Init/SimpLemmas.lean +++ b/src/Init/SimpLemmas.lean @@ -103,18 +103,26 @@ end SimprocHelperLemmas @[simp] theorem and_true (p : Prop) : (p ∧ True) = p := propext ⟨(·.1), (⟨·, trivial⟩)⟩ @[simp] theorem true_and (p : Prop) : (True ∧ p) = p := propext ⟨(·.2), (⟨trivial, ·⟩)⟩ +instance : Std.LawfulIdentity And True where + left_id := true_and + right_id := and_true @[simp] theorem and_false (p : Prop) : (p ∧ False) = False := eq_false (·.2) @[simp] theorem false_and (p : Prop) : (False ∧ p) = False := eq_false (·.1) @[simp] theorem and_self (p : Prop) : (p ∧ p) = p := propext ⟨(·.left), fun h => ⟨h, h⟩⟩ +instance : Std.IdempotentOp And := ⟨and_self⟩ @[simp] theorem and_not_self : ¬(a ∧ ¬a) | ⟨ha, hn⟩ => absurd ha hn @[simp] theorem not_and_self : ¬(¬a ∧ a) := and_not_self ∘ And.symm @[simp] theorem and_imp : (a ∧ b → c) ↔ (a → b → c) := ⟨fun h ha hb => h ⟨ha, hb⟩, fun h ⟨ha, hb⟩ => h ha hb⟩ @[simp] theorem not_and : ¬(a ∧ b) ↔ (a → ¬b) := and_imp @[simp] theorem or_self (p : Prop) : (p ∨ p) = p := propext ⟨fun | .inl h | .inr h => h, .inl⟩ +instance : Std.IdempotentOp Or := ⟨or_self⟩ @[simp] theorem or_true (p : Prop) : (p ∨ True) = True := eq_true (.inr trivial) @[simp] theorem true_or (p : Prop) : (True ∨ p) = True := eq_true (.inl trivial) @[simp] theorem or_false (p : Prop) : (p ∨ False) = p := propext ⟨fun (.inl h) => h, .inl⟩ @[simp] theorem false_or (p : Prop) : (False ∨ p) = p := propext ⟨fun (.inr h) => h, .inr⟩ +instance : Std.LawfulIdentity Or False where + left_id := false_or + right_id := or_false @[simp] theorem iff_self (p : Prop) : (p ↔ p) = True := eq_true .rfl @[simp] theorem iff_true (p : Prop) : (p ↔ True) = p := propext ⟨(·.2 trivial), fun h => ⟨fun _ => trivial, fun _ => h⟩⟩ @[simp] theorem true_iff (p : Prop) : (True ↔ p) = p := propext ⟨(·.1 trivial), fun h => ⟨fun _ => h, fun _ => trivial⟩⟩ @@ -140,6 +148,7 @@ theorem and_congr_left (h : c → (a ↔ b)) : a ∧ c ↔ b ∧ c := theorem and_assoc : (a ∧ b) ∧ c ↔ a ∧ (b ∧ c) := Iff.intro (fun ⟨⟨ha, hb⟩, hc⟩ => ⟨ha, hb, hc⟩) (fun ⟨ha, hb, hc⟩ => ⟨⟨ha, hb⟩, hc⟩) +instance : Std.Associative And := ⟨fun _ _ _ => propext and_assoc⟩ @[simp] theorem and_self_left : a ∧ (a ∧ b) ↔ a ∧ b := by rw [←propext and_assoc, and_self] @[simp] theorem and_self_right : (a ∧ b) ∧ b ↔ a ∧ b := by rw [ propext and_assoc, and_self] @@ -167,6 +176,7 @@ theorem Or.imp_right (f : b → c) : a ∨ b → a ∨ c := .imp id f theorem or_assoc : (a ∨ b) ∨ c ↔ a ∨ (b ∨ c) := Iff.intro (.rec (.imp_right .inl) (.inr ∘ .inr)) (.rec (.inl ∘ .inl) (.imp_left .inr)) +instance : Std.Associative Or := ⟨fun _ _ _ => propext or_assoc⟩ @[simp] theorem or_self_left : a ∨ (a ∨ b) ↔ a ∨ b := by rw [←propext or_assoc, or_self] @[simp] theorem or_self_right : (a ∨ b) ∨ b ↔ a ∨ b := by rw [ propext or_assoc, or_self] @@ -187,8 +197,12 @@ theorem or_iff_left_of_imp (hb : b → a) : (a ∨ b) ↔ a := Iff.intro (Or.r @[simp] theorem Bool.or_false (b : Bool) : (b || false) = b := by cases b <;> rfl @[simp] theorem Bool.or_true (b : Bool) : (b || true) = true := by cases b <;> rfl @[simp] theorem Bool.false_or (b : Bool) : (false || b) = b := by cases b <;> rfl +instance : Std.LawfulIdentity (· || ·) false where + left_id := Bool.false_or + right_id := Bool.or_false @[simp] theorem Bool.true_or (b : Bool) : (true || b) = true := by cases b <;> rfl @[simp] theorem Bool.or_self (b : Bool) : (b || b) = b := by cases b <;> rfl +instance : Std.IdempotentOp (· || ·) := ⟨Bool.or_self⟩ @[simp] theorem Bool.or_eq_true (a b : Bool) : ((a || b) = true) = (a = true ∨ b = true) := by cases a <;> cases b <;> decide @@ -196,14 +210,20 @@ theorem or_iff_left_of_imp (hb : b → a) : (a ∨ b) ↔ a := Iff.intro (Or.r @[simp] theorem Bool.and_true (b : Bool) : (b && true) = b := by cases b <;> rfl @[simp] theorem Bool.false_and (b : Bool) : (false && b) = false := by cases b <;> rfl @[simp] theorem Bool.true_and (b : Bool) : (true && b) = b := by cases b <;> rfl +instance : Std.LawfulIdentity (· && ·) true where + left_id := Bool.true_and + right_id := Bool.and_true @[simp] theorem Bool.and_self (b : Bool) : (b && b) = b := by cases b <;> rfl +instance : Std.IdempotentOp (· && ·) := ⟨Bool.and_self⟩ @[simp] theorem Bool.and_eq_true (a b : Bool) : ((a && b) = true) = (a = true ∧ b = true) := by cases a <;> cases b <;> decide theorem Bool.and_assoc (a b c : Bool) : (a && b && c) = (a && (b && c)) := by cases a <;> cases b <;> cases c <;> decide +instance : Std.Associative (· && ·) := ⟨Bool.and_assoc⟩ theorem Bool.or_assoc (a b c : Bool) : (a || b || c) = (a || (b || c)) := by cases a <;> cases b <;> cases c <;> decide +instance : Std.Associative (· || ·) := ⟨Bool.or_assoc⟩ @[simp] theorem Bool.not_not (b : Bool) : (!!b) = b := by cases b <;> rfl @[simp] theorem Bool.not_true : (!true) = false := by decide diff --git a/tests/lean/run/ac_rfl.lean b/tests/lean/run/ac_rfl.lean index adebc67845..80f3dcbb95 100644 --- a/tests/lean/run/ac_rfl.lean +++ b/tests/lean/run/ac_rfl.lean @@ -1,65 +1,3 @@ -open Std - -instance : Associative (α := Nat) HAdd.hAdd := ⟨Nat.add_assoc⟩ -instance : Commutative (α := Nat) HAdd.hAdd := ⟨Nat.add_comm⟩ -instance : LawfulCommIdentity HAdd.hAdd 0 where right_id := Nat.add_zero - -instance : Associative (α := Nat) HMul.hMul := ⟨Nat.mul_assoc⟩ -instance : Commutative (α := Nat) HMul.hMul := ⟨Nat.mul_comm⟩ -instance : LawfulCommIdentity HMul.hMul 1 where right_id := Nat.mul_one - -@[simp] theorem succ_le_succ_iff {x y : Nat} : x.succ ≤ y.succ ↔ x ≤ y := - ⟨Nat.le_of_succ_le_succ, Nat.succ_le_succ⟩ - -@[simp] theorem add_le_add_right_iff {x y z : Nat} : x + z ≤ y + z ↔ x ≤ y := by - induction z <;> simp_all [← Nat.add_assoc] - -set_option linter.unusedVariables false in -theorem le_ext : ∀ {x y : Nat} (h : ∀ z, z ≤ x ↔ z ≤ y), x = y - | 0, 0, _ => rfl - | x+1, y+1, h => congrArg (· + 1) <| le_ext fun z => have := h (z + 1); by simp at this; assumption - | 0, y+1, h => have := h 1; by clear h; simp_all - | x+1, 0, h => have := h 1; by simp at this - -theorem le_or_le : ∀ (a b : Nat), a ≤ b ∨ b ≤ a - | x+1, y+1 => by simp [le_or_le x y] - | 0, 0 | x+1, 0 | 0, y+1 => by simp - -theorem le_of_not_le {a b : Nat} (h : ¬ a ≤ b) : b ≤ a := - match le_or_le a b with | .inl ab => (h ab).rec | .inr ba => ba - -@[simp] theorem le_max_iff {x y z : Nat} : x ≤ max y z ↔ x ≤ y ∨ x ≤ z := by - simp only [Nat.max_def] - split - · exact Iff.intro .inr fun | .inl xy => Nat.le_trans ‹_› ‹_› | .inr xz => ‹_› - · exact Iff.intro .inl fun | .inl xy => ‹_› | .inr xz => Nat.le_trans ‹_› (le_of_not_le ‹_›) - -theorem max_assoc (n m k : Nat) : max (max n m) k = max n (max m k) := - le_ext (by simp [or_assoc]) - -theorem max_comm (n m : Nat) : max n m = max m n := - le_ext (by simp [or_comm]) - -theorem max_idem (n : Nat) : max n n = n := le_ext (by simp) - -instance : Associative (α := Nat) max := ⟨max_assoc⟩ -instance : Commutative (α := Nat) max := ⟨max_comm⟩ -instance : IdempotentOp (α := Nat) max := ⟨max_idem⟩ -instance : LawfulCommIdentity max 0 where - right_id := Nat.max_zero - -instance : Associative And := ⟨λ _p _q _r => propext ⟨λ ⟨⟨hp, hq⟩, hr⟩ => ⟨hp, hq, hr⟩, λ ⟨hp, hq, hr⟩ => ⟨⟨hp, hq⟩, hr⟩⟩⟩ -instance : Commutative And := ⟨λ _p _q => propext ⟨λ ⟨hp, hq⟩ => ⟨hq, hp⟩, λ ⟨hq, hp⟩ => ⟨hp, hq⟩⟩⟩ -instance : IdempotentOp And := ⟨λ _p => propext ⟨λ ⟨hp, _⟩ => hp, λ hp => ⟨hp, hp⟩⟩⟩ -instance : LawfulCommIdentity And True where - right_id _p := propext ⟨λ ⟨hp, _⟩ => hp, λ hp => ⟨hp, True.intro⟩⟩ - -instance : Associative Or := ⟨by simp [or_assoc]⟩ -instance : Commutative Or := ⟨λ_p _q => propext ⟨λ hpq => hpq.elim Or.inr Or.inl, λ hqp => hqp.elim Or.inr Or.inl⟩⟩ -instance : IdempotentOp Or := ⟨λ_p => propext ⟨λ hp => hp.elim id id, Or.inl⟩⟩ -instance : LawfulCommIdentity Or False where - right_id _p := propext ⟨λ hpf => hpf.elim id False.elim, Or.inl⟩ - example (x y z : Nat) : x + y + 0 + z = z + (x + y) := by ac_rfl example (x y z : Nat) : (x + y) * (0 + z) = (x + y) * z:= by ac_rfl @@ -96,3 +34,5 @@ example (p q : Prop) : (p ∨ p ∨ q ∧ True) = (q ∨ p) := by -- Repro: missing withContext example : ∀ x : Nat, x = x := by intro x; ac_rfl + +example : [1, 2] ++ ([] ++ [2+4, 8] ++ [4]) = [1, 2] ++ [4+2, 8] ++ [4] := by ac_rfl