|
| 1 | +/- |
| 2 | +Copyright (c) 2021 Damiano Testa. All rights reserved. |
| 3 | +Released under Apache 2.0 license as described in the file LICENSE. |
| 4 | +Authors: Damiano Testa |
| 5 | +-/ |
| 6 | +import Mathlib.Algebra.Group.Defs |
| 7 | +import Mathlib.Order.Basic |
| 8 | +import Mathlib.Order.Monotone |
| 9 | + |
| 10 | +/-! |
| 11 | +
|
| 12 | +# Covariants and contravariants |
| 13 | +
|
| 14 | +This file contains general lemmas and instances to work with the interactions between a relation and |
| 15 | +an action on a Type. |
| 16 | +
|
| 17 | +The intended application is the splitting of the ordering from the algebraic assumptions on the |
| 18 | +operations in the `ordered_[...]` hierarchy. |
| 19 | +
|
| 20 | +The strategy is to introduce two more flexible typeclasses, `CovariantClass` and |
| 21 | +`ContravariantClass`: |
| 22 | +
|
| 23 | +* `CovariantClass` models the implication `a ≤ b → c * a ≤ c * b` (multiplication is monotone), |
| 24 | +* `ContravariantClass` models the implication `a * b < a * c → b < c`. |
| 25 | +
|
| 26 | +Since `co(ntra)variant_class` takes as input the operation (typically `(+)` or `(*)`) and the order |
| 27 | +relation (typically `(≤)` or `(<)`), these are the only two typeclasses that I have used. |
| 28 | +
|
| 29 | +The general approach is to formulate the lemma that you are interested in and prove it, with the |
| 30 | +`ordered_[...]` typeclass of your liking. After that, you convert the single typeclass, |
| 31 | +say `[ordered_cancel_monoid M]`, into three typeclasses, e.g. |
| 32 | +`[left_cancel_semigroup M] [partial_order M] [CovariantClass M M (function.swap (*)) (≤)]` |
| 33 | +and have a go at seeing if the proof still works! |
| 34 | +
|
| 35 | +Note that it is possible to combine several co(ntra)variant_class assumptions together. |
| 36 | +Indeed, the usual ordered typeclasses arise from assuming the pair |
| 37 | +`[CovariantClass M M (*) (≤)] [ContravariantClass M M (*) (<)]` |
| 38 | +on top of order/algebraic assumptions. |
| 39 | +
|
| 40 | +A formal remark is that normally `CovariantClass` uses the `(≤)`-relation, while |
| 41 | +`ContravariantClass` uses the `(<)`-relation. This need not be the case in general, but seems to be |
| 42 | +the most common usage. In the opposite direction, the implication |
| 43 | +```lean |
| 44 | +[semigroup α] [partial_order α] [ContravariantClass α α (*) (≤)] => left_cancel_semigroup α |
| 45 | +``` |
| 46 | +holds -- note the `co*ntra*` assumption on the `(≤)`-relation. |
| 47 | +
|
| 48 | +# Formalization notes |
| 49 | +
|
| 50 | +We stick to the convention of using `function.swap (*)` (or `function.swap (+)`), for the |
| 51 | +typeclass assumptions, since `function.swap` is slightly better behaved than `flip`. |
| 52 | +However, sometimes as a **non-typeclass** assumption, we prefer `flip (*)` (or `flip (+)`), |
| 53 | +as it is easier to use. |
| 54 | +
|
| 55 | +
|
| 56 | +# Porting notes |
| 57 | +
|
| 58 | +In mathlib3 we used the `is_trans` typeclass from Lean 3 core, |
| 59 | +and we have switched to the `Trans` typeclass from Lean 4 core. |
| 60 | +
|
| 61 | +-/ |
| 62 | + |
| 63 | + |
| 64 | +-- TODO: convert `has_exists_mul_of_le`, `has_exists_add_of_le`? |
| 65 | +-- TODO: relationship with `con/add_con` |
| 66 | +-- TODO: include equivalence of `left_cancel_semigroup` with |
| 67 | +-- `semigroup partial_order ContravariantClass α α (*) (≤)`? |
| 68 | +-- TODO : use ⇒, as per Eric's suggestion? See |
| 69 | +-- https://leanprover.zulipchat.com/#narrow/stream/116395-maths/topic/ordered.20stuff/near/236148738 |
| 70 | +-- for a discussion. |
| 71 | +open Function |
| 72 | + |
| 73 | +section Variants |
| 74 | + |
| 75 | +variable {M N : Type _} (μ : M → N → N) (r : N → N → Prop) |
| 76 | + |
| 77 | +variable (M N) |
| 78 | + |
| 79 | +/-- `Covariant` is useful to formulate succintly statements about the interactions between an |
| 80 | +action of a Type on another one and a relation on the acted-upon Type. |
| 81 | +
|
| 82 | +See the `CovariantClass` doc-string for its meaning. -/ |
| 83 | +def Covariant : Prop := |
| 84 | + ∀ (m) {n₁ n₂}, r n₁ n₂ → r (μ m n₁) (μ m n₂) |
| 85 | + |
| 86 | +/-- `Contravariant` is useful to formulate succintly statements about the interactions between an |
| 87 | +action of a Type on another one and a relation on the acted-upon Type. |
| 88 | +
|
| 89 | +See the `ContravariantClass` doc-string for its meaning. -/ |
| 90 | +def Contravariant : Prop := |
| 91 | + ∀ (m) {n₁ n₂}, r (μ m n₁) (μ m n₂) → r n₁ n₂ |
| 92 | + |
| 93 | +/-- Given an action `μ` of a Type `M` on a Type `N` and a relation `r` on `N`, informally, the |
| 94 | +`CovariantClass` says that "the action `μ` preserves the relation `r`." |
| 95 | +
|
| 96 | +More precisely, the `CovariantClass` is a class taking two Types `M N`, together with an "action" |
| 97 | +`μ : M → N → N` and a relation `r : N → N → Prop`. Its unique field `elim` is the assertion that |
| 98 | +for all `m ∈ M` and all elements `n₁, n₂ ∈ N`, if the relation `r` holds for the pair |
| 99 | +`(n₁, n₂)`, then, the relation `r` also holds for the pair `(μ m n₁, μ m n₂)`, |
| 100 | +obtained from `(n₁, n₂)` by acting upon it by `m`. |
| 101 | +
|
| 102 | +If `m : M` and `h : r n₁ n₂`, then `CovariantClass.elim m h : r (μ m n₁) (μ m n₂)`. |
| 103 | +-/ |
| 104 | +class CovariantClass : Prop where |
| 105 | + /-- For all `m ∈ M` and all elements `n₁, n₂ ∈ N`, if the relation `r` holds for the pair |
| 106 | + `(n₁, n₂)`, then, the relation `r` also holds for the pair `(μ m n₁, μ m n₂)` -/ |
| 107 | + protected elim : Covariant M N μ r |
| 108 | + |
| 109 | +/-- Given an action `μ` of a Type `M` on a Type `N` and a relation `r` on `N`, informally, the |
| 110 | +`ContravariantClass` says that "if the result of the action `μ` on a pair satisfies the |
| 111 | +relation `r`, then the initial pair satisfied the relation `r`." |
| 112 | +
|
| 113 | +More precisely, the `ContravariantClass` is a class taking two Types `M N`, together with an |
| 114 | +"action" `μ : M → N → N` and a relation `r : N → N → Prop`. Its unique field `elim` is the |
| 115 | +assertion that for all `m ∈ M` and all elements `n₁, n₂ ∈ N`, if the relation `r` holds for the |
| 116 | +pair `(μ m n₁, μ m n₂)` obtained from `(n₁, n₂)` by acting upon it by `m`, then, the relation |
| 117 | +`r` also holds for the pair `(n₁, n₂)`. |
| 118 | +
|
| 119 | +If `m : M` and `h : r (μ m n₁) (μ m n₂)`, then `ContravariantClass.elim m h : r n₁ n₂`. |
| 120 | +-/ |
| 121 | +class ContravariantClass : Prop where |
| 122 | + /-- For all `m ∈ M` and all elements `n₁, n₂ ∈ N`, if the relation `r` holds for the |
| 123 | + pair `(μ m n₁, μ m n₂)` obtained from `(n₁, n₂)` by acting upon it by `m`, then, the relation |
| 124 | + `r` also holds for the pair `(n₁, n₂)`. -/ |
| 125 | + protected elim : Contravariant M N μ r |
| 126 | + |
| 127 | +theorem rel_iff_cov [CovariantClass M N μ r] [ContravariantClass M N μ r] (m : M) {a b : N} : |
| 128 | + r (μ m a) (μ m b) ↔ r a b := |
| 129 | + ⟨ContravariantClass.elim _, CovariantClass.elim _⟩ |
| 130 | + |
| 131 | +section flip |
| 132 | + |
| 133 | +variable {M N μ r} |
| 134 | + |
| 135 | +theorem Covariant.flip (h : Covariant M N μ r) : Covariant M N μ (flip r) := |
| 136 | + fun a _ _ hbc => h a hbc |
| 137 | + |
| 138 | +theorem Contravariant.flip (h : Contravariant M N μ r) : Contravariant M N μ (flip r) := |
| 139 | + fun a _ _ hbc => h a hbc |
| 140 | + |
| 141 | +end flip |
| 142 | + |
| 143 | +section Covariant |
| 144 | + |
| 145 | +variable {M N μ r} [CovariantClass M N μ r] |
| 146 | + |
| 147 | +theorem act_rel_act_of_rel (m : M) {a b : N} (ab : r a b) : r (μ m a) (μ m b) := |
| 148 | + CovariantClass.elim _ ab |
| 149 | + |
| 150 | +@[to_additive] |
| 151 | +theorem Group.covariant_iff_contravariant [Group N] : |
| 152 | + Covariant N N (· * ·) r ↔ Contravariant N N (· * ·) r := by |
| 153 | + refine ⟨fun h a b c bc => ?_, fun h a b c bc => ?_⟩ |
| 154 | + · rw [← inv_mul_cancel_left a b, ← inv_mul_cancel_left a c] |
| 155 | + exact h a⁻¹ bc |
| 156 | + · rw [← inv_mul_cancel_left a b, ← inv_mul_cancel_left a c] at bc |
| 157 | + exact h a⁻¹ bc |
| 158 | + |
| 159 | +@[to_additive] |
| 160 | +instance (priority := 100) Group.covconv [Group N] [CovariantClass N N (· * ·) r] : |
| 161 | + ContravariantClass N N (· * ·) r := |
| 162 | + ⟨Group.covariant_iff_contravariant.mp CovariantClass.elim⟩ |
| 163 | + |
| 164 | +-- Porting note: as at 2022-11-13, `to_additive` doesn't copy the `instance` attribute |
| 165 | +-- so we need to do it manually. I don't know how to copy the priority. |
| 166 | +attribute [instance] AddGroup.covconv |
| 167 | + |
| 168 | +@[to_additive] |
| 169 | +theorem Group.covariant_swap_iff_contravariant_swap [Group N] : |
| 170 | + Covariant N N (swap (· * ·)) r ↔ Contravariant N N (swap (· * ·)) r := by |
| 171 | + refine ⟨fun h a b c bc => ?_, fun h a b c bc => ?_⟩ |
| 172 | + · rw [← mul_inv_cancel_right b a, ← mul_inv_cancel_right c a] |
| 173 | + exact h a⁻¹ bc |
| 174 | + · rw [← mul_inv_cancel_right b a, ← mul_inv_cancel_right c a] at bc |
| 175 | + exact h a⁻¹ bc |
| 176 | + |
| 177 | + |
| 178 | +@[to_additive] |
| 179 | +instance (priority := 100) Group.covconv_swap [Group N] [CovariantClass N N (swap (· * ·)) r] : |
| 180 | + ContravariantClass N N (swap (· * ·)) r := |
| 181 | + ⟨Group.covariant_swap_iff_contravariant_swap.mp CovariantClass.elim⟩ |
| 182 | + |
| 183 | +attribute [instance] AddGroup.covconv_swap |
| 184 | + |
| 185 | +section Trans |
| 186 | + |
| 187 | +variable [Trans r r r] (m n : M) {a b c d : N} |
| 188 | + |
| 189 | +-- Lemmas with 3 elements. |
| 190 | +theorem act_rel_of_rel_of_act_rel (ab : r a b) (rl : r (μ m b) c) : r (μ m a) c := |
| 191 | + trans (act_rel_act_of_rel m ab) rl |
| 192 | + |
| 193 | +theorem rel_act_of_rel_of_rel_act (ab : r a b) (rr : r c (μ m a)) : r c (μ m b) := |
| 194 | + trans rr (act_rel_act_of_rel _ ab) |
| 195 | + |
| 196 | +end Trans |
| 197 | + |
| 198 | +end Covariant |
| 199 | + |
| 200 | +-- Lemma with 4 elements. |
| 201 | +section MEqN |
| 202 | + |
| 203 | +variable {M N μ r} {mu : N → N → N} [Trans r r r] [i : CovariantClass N N mu r] |
| 204 | + [i' : CovariantClass N N (swap mu) r] {a b c d : N} |
| 205 | + |
| 206 | +theorem act_rel_act_of_rel_of_rel (ab : r a b) (cd : r c d) : r (mu a c) (mu b d) := |
| 207 | + trans (@act_rel_act_of_rel _ _ (swap mu) r _ c _ _ ab) (act_rel_act_of_rel b cd) |
| 208 | + |
| 209 | +end MEqN |
| 210 | + |
| 211 | +section Contravariant |
| 212 | + |
| 213 | +variable {M N μ r} [ContravariantClass M N μ r] |
| 214 | + |
| 215 | +theorem rel_of_act_rel_act (m : M) {a b : N} (ab : r (μ m a) (μ m b)) : r a b := |
| 216 | + ContravariantClass.elim _ ab |
| 217 | + |
| 218 | +section Trans |
| 219 | + |
| 220 | +variable [Trans r r r] (m n : M) {a b c d : N} |
| 221 | + |
| 222 | +-- Lemmas with 3 elements. |
| 223 | +theorem act_rel_of_act_rel_of_rel_act_rel (ab : r (μ m a) b) (rl : r (μ m b) (μ m c)) : |
| 224 | + r (μ m a) c := |
| 225 | + trans ab (rel_of_act_rel_act m rl) |
| 226 | + |
| 227 | +theorem rel_act_of_act_rel_act_of_rel_act (ab : r (μ m a) (μ m b)) (rr : r b (μ m c)) : |
| 228 | + r a (μ m c) := |
| 229 | + trans (rel_of_act_rel_act m ab) rr |
| 230 | + |
| 231 | +end Trans |
| 232 | + |
| 233 | +end Contravariant |
| 234 | + |
| 235 | +section Monotone |
| 236 | + |
| 237 | +variable {α : Type _} {M N μ} [Preorder α] [Preorder N] |
| 238 | + |
| 239 | +variable {f : N → α} |
| 240 | + |
| 241 | +/-- The partial application of a constant to a covariant operator is monotone. -/ |
| 242 | +theorem Covariant.monotone_of_const [CovariantClass M N μ (· ≤ ·)] (m : M) : Monotone (μ m) := |
| 243 | + fun _ _ ha => CovariantClass.elim m ha |
| 244 | + |
| 245 | +/-- A monotone function remains monotone when composed with the partial application |
| 246 | +of a covariant operator. E.g., `∀ (m : ℕ), monotone f → monotone (λ n, f (m + n))`. -/ |
| 247 | +theorem Monotone.covariant_of_const [CovariantClass M N μ (· ≤ ·)] (hf : Monotone f) (m : M) : |
| 248 | + Monotone fun n => f (μ m n) := |
| 249 | + fun _ _ x => hf (Covariant.monotone_of_const m x) |
| 250 | + |
| 251 | +/-- Same as `monotone.covariant_of_const`, but with the constant on the other side of |
| 252 | +the operator. E.g., `∀ (m : ℕ), monotone f → monotone (λ n, f (n + m))`. -/ |
| 253 | +theorem Monotone.covariant_of_const' {μ : N → N → N} [CovariantClass N N (swap μ) (· ≤ ·)] |
| 254 | + (hf : Monotone f) (m : N) : Monotone fun n => f (μ n m) := |
| 255 | + fun _ _ x => hf (@Covariant.monotone_of_const _ _ (swap μ) _ _ m _ _ x) |
| 256 | + |
| 257 | +/-- Dual of `monotone.covariant_of_const` -/ |
| 258 | +theorem Antitone.covariant_of_const [CovariantClass M N μ (· ≤ ·)] (hf : Antitone f) (m : M) : |
| 259 | + Antitone fun n => f (μ m n) := |
| 260 | + hf.comp_monotone <| Covariant.monotone_of_const m |
| 261 | + |
| 262 | +/-- Dual of `monotone.covariant_of_const'` -/ |
| 263 | +theorem Antitone.covariant_of_const' {μ : N → N → N} [CovariantClass N N (swap μ) (· ≤ ·)] |
| 264 | + (hf : Antitone f) (m : N) : Antitone fun n => f (μ n m) := |
| 265 | + hf.comp_monotone <| @Covariant.monotone_of_const _ _ (swap μ) _ _ m |
| 266 | + |
| 267 | +end Monotone |
| 268 | + |
| 269 | +theorem covariant_le_of_covariant_lt [PartialOrder N] : |
| 270 | + Covariant M N μ (· < ·) → Covariant M N μ (· ≤ ·) := by |
| 271 | + intro h a b c bc |
| 272 | + rcases le_iff_eq_or_lt.mp bc with (rfl | bc) |
| 273 | + · exact rfl.le |
| 274 | + · exact (h _ bc).le |
| 275 | + |
| 276 | +theorem contravariant_lt_of_contravariant_le [PartialOrder N] : |
| 277 | + Contravariant M N μ (· ≤ ·) → Contravariant M N μ (· < ·) := by |
| 278 | + refine fun h a b c bc => lt_iff_le_and_ne.mpr ⟨h a bc.le, ?_⟩ |
| 279 | + rintro rfl; exact lt_irrefl _ bc |
| 280 | + |
| 281 | +theorem covariant_le_iff_contravariant_lt [LinearOrder N] : |
| 282 | + Covariant M N μ (· ≤ ·) ↔ Contravariant M N μ (· < ·) := |
| 283 | + ⟨fun h _ _ _ bc => not_le.mp fun k => not_le.mpr bc (h _ k), |
| 284 | + fun h _ _ _ bc => not_lt.mp fun k => not_lt.mpr bc (h _ k)⟩ |
| 285 | + |
| 286 | +theorem covariant_lt_iff_contravariant_le [LinearOrder N] : |
| 287 | + Covariant M N μ (· < ·) ↔ Contravariant M N μ (· ≤ ·) := |
| 288 | + ⟨fun h _ _ _ bc => not_lt.mp fun k => not_lt.mpr bc (h _ k), |
| 289 | + fun h _ _ _ bc => not_le.mp fun k => not_le.mpr bc (h _ k)⟩ |
| 290 | + |
| 291 | +-- Porting note: `covariant_flip_mul_iff` used to use the `IsSymmOp` typeclass from Lean 3 core. |
| 292 | +-- To avoid it, we prove the relevant lemma here. |
| 293 | +@[to_additive] |
| 294 | +lemma flip_mul [CommSemigroup N] : (flip (· * ·) : N → N → N) = (· * ·) := |
| 295 | + funext fun a => funext fun b => mul_comm b a |
| 296 | + |
| 297 | +@[to_additive] |
| 298 | +theorem covariant_flip_mul_iff [CommSemigroup N] : |
| 299 | + Covariant N N (flip (· * ·)) r ↔ Covariant N N (· * ·) r := by rw [flip_mul] |
| 300 | + |
| 301 | +@[to_additive] |
| 302 | +theorem contravariant_flip_mul_iff [CommSemigroup N] : |
| 303 | + Contravariant N N (flip (· * ·)) r ↔ Contravariant N N (· * ·) r := by rw [flip_mul] |
| 304 | + |
| 305 | +@[to_additive] |
| 306 | +instance contravariant_mul_lt_of_covariant_mul_le [Mul N] [LinearOrder N] |
| 307 | + [CovariantClass N N (· * ·) (· ≤ ·)] : ContravariantClass N N (· * ·) (· < ·) where |
| 308 | + elim := (covariant_le_iff_contravariant_lt N N (· * ·)).mp CovariantClass.elim |
| 309 | + |
| 310 | +attribute [instance] contravariant_add_lt_of_covariant_add_le |
| 311 | + |
| 312 | +@[to_additive] |
| 313 | +instance covariant_mul_lt_of_contravariant_mul_le [Mul N] [LinearOrder N] |
| 314 | + [ContravariantClass N N (· * ·) (· ≤ ·)] : CovariantClass N N (· * ·) (· < ·) where |
| 315 | + elim := (covariant_lt_iff_contravariant_le N N (· * ·)).mpr ContravariantClass.elim |
| 316 | + |
| 317 | +attribute [instance] covariant_add_lt_of_contravariant_add_le |
| 318 | + |
| 319 | +@[to_additive] |
| 320 | +instance covariant_swap_mul_le_of_covariant_mul_le [CommSemigroup N] [LE N] |
| 321 | + [CovariantClass N N (· * ·) (· ≤ ·)] : CovariantClass N N (swap (· * ·)) (· ≤ ·) where |
| 322 | + elim := (covariant_flip_mul_iff N (· ≤ ·)).mpr CovariantClass.elim |
| 323 | + |
| 324 | +attribute [instance] covariant_swap_add_le_of_covariant_add_le |
| 325 | + |
| 326 | +@[to_additive] |
| 327 | +instance contravariant_swap_mul_le_of_contravariant_mul_le [CommSemigroup N] [LE N] |
| 328 | + [ContravariantClass N N (· * ·) (· ≤ ·)] : ContravariantClass N N (swap (· * ·)) (· ≤ ·) where |
| 329 | + elim := (contravariant_flip_mul_iff N (· ≤ ·)).mpr ContravariantClass.elim |
| 330 | + |
| 331 | +attribute [instance] contravariant_swap_add_le_of_contravariant_add_le |
| 332 | + |
| 333 | +@[to_additive] |
| 334 | +instance contravariant_swap_mul_lt_of_contravariant_mul_lt [CommSemigroup N] [LT N] |
| 335 | + [ContravariantClass N N (· * ·) (· < ·)] : ContravariantClass N N (swap (· * ·)) (· < ·) where |
| 336 | + elim := (contravariant_flip_mul_iff N (· < ·)).mpr ContravariantClass.elim |
| 337 | + |
| 338 | +attribute [instance] contravariant_swap_add_lt_of_contravariant_add_lt |
| 339 | + |
| 340 | +@[to_additive] |
| 341 | +instance covariant_swap_mul_lt_of_covariant_mul_lt [CommSemigroup N] [LT N] |
| 342 | + [CovariantClass N N (· * ·) (· < ·)] : CovariantClass N N (swap (· * ·)) (· < ·) where |
| 343 | + elim := (covariant_flip_mul_iff N (· < ·)).mpr CovariantClass.elim |
| 344 | + |
| 345 | +attribute [instance] covariant_swap_add_lt_of_covariant_add_lt |
| 346 | + |
| 347 | +@[to_additive] |
| 348 | +instance LeftCancelSemigroup.covariant_mul_lt_of_covariant_mul_le [LeftCancelSemigroup N] |
| 349 | + [PartialOrder N] [CovariantClass N N (· * ·) (· ≤ ·)] : |
| 350 | + CovariantClass N N (· * ·) (· < ·) where |
| 351 | + elim a b c bc := by |
| 352 | + cases' lt_iff_le_and_ne.mp bc with bc cb |
| 353 | + exact lt_iff_le_and_ne.mpr ⟨CovariantClass.elim a bc, (mul_ne_mul_right a).mpr cb⟩ |
| 354 | + |
| 355 | +attribute [instance] AddLeftCancelSemigroup.covariant_add_lt_of_covariant_add_le |
| 356 | + |
| 357 | +@[to_additive] |
| 358 | +instance RightCancelSemigroup.covariant_swap_mul_lt_of_covariant_swap_mul_le |
| 359 | + [RightCancelSemigroup N] [PartialOrder N] [CovariantClass N N (swap (· * ·)) (· ≤ ·)] : |
| 360 | + CovariantClass N N (swap (· * ·)) (· < ·) where |
| 361 | + elim a b c bc := by |
| 362 | + cases' lt_iff_le_and_ne.mp bc with bc cb |
| 363 | + exact lt_iff_le_and_ne.mpr ⟨CovariantClass.elim a bc, (mul_ne_mul_left a).mpr cb⟩ |
| 364 | + |
| 365 | +attribute [instance] AddRightCancelSemigroup.covariant_swap_add_lt_of_covariant_swap_add_le |
| 366 | + |
| 367 | +@[to_additive] |
| 368 | +instance LeftCancelSemigroup.contravariant_mul_le_of_contravariant_mul_lt [LeftCancelSemigroup N] |
| 369 | + [PartialOrder N] [ContravariantClass N N (· * ·) (· < ·)] : |
| 370 | + ContravariantClass N N (· * ·) (· ≤ ·) where |
| 371 | + elim a b c bc := by |
| 372 | + cases' le_iff_eq_or_lt.mp bc with h h |
| 373 | + · exact ((mul_right_inj a).mp h).le |
| 374 | + · exact (ContravariantClass.elim _ h).le |
| 375 | + |
| 376 | +attribute [instance] AddLeftCancelSemigroup.contravariant_add_le_of_contravariant_add_lt |
| 377 | + |
| 378 | +@[to_additive] |
| 379 | +instance RightCancelSemigroup.contravariant_swap_mul_le_of_contravariant_swap_mul_lt |
| 380 | + [RightCancelSemigroup N] [PartialOrder N] [ContravariantClass N N (swap (· * ·)) (· < ·)] : |
| 381 | + ContravariantClass N N (swap (· * ·)) (· ≤ ·) where |
| 382 | + elim a b c bc := by |
| 383 | + cases' le_iff_eq_or_lt.mp bc with h h |
| 384 | + · exact ((mul_left_inj a).mp h).le |
| 385 | + · exact (ContravariantClass.elim _ h).le |
| 386 | + |
| 387 | +attribute [instance] AddRightCancelSemigroup.contravariant_swap_add_le_of_contravariant_swap_add_lt |
| 388 | + |
| 389 | +end Variants |
0 commit comments