/-
Copyright (c) 2022 Junyan Xu. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Damiano Testa, Junyan Xu

! This file was ported from Lean 3 source module data.dfinsupp.lex
! leanprover-community/mathlib commit 34ee86e6a59d911a8e4f89b68793ee7577ae79c7
! Please do not edit these lines, except to modify the commit id
! if you have ported upstream changes.
-/
import Mathbin.Data.Dfinsupp.Order
import Mathbin.Data.Dfinsupp.NeLocus
import Mathbin.Order.WellFoundedSet

/-!
# Lexicographic order on finitely supported dependent functions

> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
> Any changes to this file require a corresponding PR to mathlib4.

This file defines the lexicographic order on `dfinsupp`.
-/

variable {ι : Type _} {α : ι → Type _}

namespace Dfinsupp

section Zero

variable [∀ i, Zero (α i)]

#print Dfinsupp.Lex /-
/-- `dfinsupp.lex r s` is the lexicographic relation on `Π₀ i, α i`, where `ι` is ordered by `r`,
and `α i` is ordered by `s i`.
The type synonym `lex (Π₀ i, α i)` has an order given by `dfinsupp.lex (<) (λ i, (<))`.
-/
protected def Lex (r : ι → ι → Prop) (s : ∀ i, α i → α i → Prop) (x y : Π₀ i, α i) : Prop :=
  Pi.Lex r s x y
#align dfinsupp.lex Dfinsupp.Lex
-/

/- warning: pi.lex_eq_dfinsupp_lex -> Pi.lex_eq_dfinsupp_lex is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : forall (i : ι), Zero.{u2} (α i)] {r : ι -> ι -> Prop} {s : forall (i : ι), (α i) -> (α i) -> Prop} (a : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (b : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)), Eq.{1} Prop (Pi.Lex.{u1, u2} ι (fun (i : ι) => α i) r s (coeFn.{succ (max u1 u2), max (succ u1) (succ u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (fun (_x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => forall (i : ι), α i) (Dfinsupp.hasCoeToFun.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) a) (coeFn.{succ (max u1 u2), max (succ u1) (succ u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (fun (_x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => forall (i : ι), α i) (Dfinsupp.hasCoeToFun.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) b)) (Dfinsupp.Lex.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) r s a b)
but is expected to have type
  forall {ι : Type.{u2}} {α : ι -> Type.{u1}} [_inst_1 : forall (i : ι), Zero.{u1} (α i)] {r : ι -> ι -> Prop} {s : forall (i : ι), (α i) -> (α i) -> Prop} (a : Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (b : Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)), Eq.{1} Prop (Pi.Lex.{u2, u1} ι (fun {i : ι} => α i) r (fun {i._@.Mathlib.Data.Dfinsupp.Lex._hyg.178 : ι} => s i._@.Mathlib.Data.Dfinsupp.Lex._hyg.178) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Dfinsupp.{u2, u1} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) ι (fun (_x : ι) => (fun (i : ι) => (fun (i : ι) => α i) i) _x) (Dfinsupp.funLike.{u2, u1} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) a) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Dfinsupp.{u2, u1} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) ι (fun (_x : ι) => (fun (i : ι) => (fun (i : ι) => α i) i) _x) (Dfinsupp.funLike.{u2, u1} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) b)) (Dfinsupp.Lex.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) r s a b)
Case conversion may be inaccurate. Consider using '#align pi.lex_eq_dfinsupp_lex Pi.lex_eq_dfinsupp_lexₓ'. -/
theorem Pi.lex_eq_dfinsupp_lex {r : ι → ι → Prop} {s : ∀ i, α i → α i → Prop} (a b : Π₀ i, α i) :
    Pi.Lex r s (a : ∀ i, α i) b = Dfinsupp.Lex r s a b :=
  rfl
#align pi.lex_eq_dfinsupp_lex Pi.lex_eq_dfinsupp_lex

/- warning: dfinsupp.lex_def -> Dfinsupp.lex_def is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : forall (i : ι), Zero.{u2} (α i)] {r : ι -> ι -> Prop} {s : forall (i : ι), (α i) -> (α i) -> Prop} {a : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)} {b : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)}, Iff (Dfinsupp.Lex.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) r s a b) (Exists.{succ u1} ι (fun (j : ι) => And (forall (d : ι), (r d j) -> (Eq.{succ u2} (α d) (coeFn.{succ (max u1 u2), max (succ u1) (succ u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (fun (_x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => forall (i : ι), α i) (Dfinsupp.hasCoeToFun.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) a d) (coeFn.{succ (max u1 u2), max (succ u1) (succ u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (fun (_x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => forall (i : ι), α i) (Dfinsupp.hasCoeToFun.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) b d))) (s j (coeFn.{succ (max u1 u2), max (succ u1) (succ u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (fun (_x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => forall (i : ι), α i) (Dfinsupp.hasCoeToFun.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) a j) (coeFn.{succ (max u1 u2), max (succ u1) (succ u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (fun (_x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => forall (i : ι), α i) (Dfinsupp.hasCoeToFun.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) b j))))
but is expected to have type
  forall {ι : Type.{u2}} {α : ι -> Type.{u1}} [_inst_1 : forall (i : ι), Zero.{u1} (α i)] {r : ι -> ι -> Prop} {s : forall (i : ι), (α i) -> (α i) -> Prop} {a : Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)} {b : Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)}, Iff (Dfinsupp.Lex.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) r s a b) (Exists.{succ u2} ι (fun (j : ι) => And (forall (d : ι), (r d j) -> (Eq.{succ u1} ((fun (i : ι) => (fun (i : ι) => α i) i) d) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Dfinsupp.{u2, u1} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) ι (fun (_x : ι) => (fun (i : ι) => (fun (i : ι) => α i) i) _x) (Dfinsupp.funLike.{u2, u1} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) a d) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Dfinsupp.{u2, u1} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) ι (fun (_x : ι) => (fun (i : ι) => (fun (i : ι) => α i) i) _x) (Dfinsupp.funLike.{u2, u1} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) b d))) (s j (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Dfinsupp.{u2, u1} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) ι (fun (_x : ι) => (fun (i : ι) => (fun (i : ι) => α i) i) _x) (Dfinsupp.funLike.{u2, u1} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) a j) (FunLike.coe.{max (succ u2) (succ u1), succ u2, succ u1} (Dfinsupp.{u2, u1} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) ι (fun (_x : ι) => (fun (i : ι) => (fun (i : ι) => α i) i) _x) (Dfinsupp.funLike.{u2, u1} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) b j))))
Case conversion may be inaccurate. Consider using '#align dfinsupp.lex_def Dfinsupp.lex_defₓ'. -/
theorem lex_def {r : ι → ι → Prop} {s : ∀ i, α i → α i → Prop} {a b : Π₀ i, α i} :
    Dfinsupp.Lex r s a b ↔ ∃ j, (∀ d, r d j → a d = b d) ∧ s j (a j) (b j) :=
  Iff.rfl
#align dfinsupp.lex_def Dfinsupp.lex_def

instance [LT ι] [∀ i, LT (α i)] : LT (Lex (Π₀ i, α i)) :=
  ⟨fun f g => Dfinsupp.Lex (· < ·) (fun i => (· < ·)) (ofLex f) (ofLex g)⟩

/- warning: dfinsupp.lex_lt_of_lt_of_preorder -> Dfinsupp.lex_lt_of_lt_of_preorder is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : forall (i : ι), Zero.{u2} (α i)] [_inst_2 : forall (i : ι), Preorder.{u2} (α i)] (r : ι -> ι -> Prop) [_inst_3 : IsStrictOrder.{u1} ι r] {x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)} {y : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)}, (LT.lt.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (Preorder.toLT.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (Dfinsupp.preorder.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) (fun (i : ι) => _inst_2 i))) x y) -> (Exists.{succ u1} ι (fun (i : ι) => And (forall (j : ι), (r j i) -> (And (LE.le.{u2} (α j) (Preorder.toLE.{u2} (α j) (_inst_2 j)) (coeFn.{succ (max u1 u2), max (succ u1) (succ u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (fun (_x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => forall (i : ι), α i) (Dfinsupp.hasCoeToFun.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) x j) (coeFn.{succ (max u1 u2), max (succ u1) (succ u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (fun (_x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => forall (i : ι), α i) (Dfinsupp.hasCoeToFun.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) y j)) (LE.le.{u2} (α j) (Preorder.toLE.{u2} (α j) (_inst_2 j)) (coeFn.{succ (max u1 u2), max (succ u1) (succ u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (fun (_x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => forall (i : ι), α i) (Dfinsupp.hasCoeToFun.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) y j) (coeFn.{succ (max u1 u2), max (succ u1) (succ u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (fun (_x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => forall (i : ι), α i) (Dfinsupp.hasCoeToFun.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) x j)))) (LT.lt.{u2} (α i) (Preorder.toLT.{u2} (α i) (_inst_2 i)) (coeFn.{succ (max u1 u2), max (succ u1) (succ u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (fun (_x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => forall (i : ι), α i) (Dfinsupp.hasCoeToFun.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) x i) (coeFn.{succ (max u1 u2), max (succ u1) (succ u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (fun (_x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => forall (i : ι), α i) (Dfinsupp.hasCoeToFun.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) y i))))
but is expected to have type
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : forall (i : ι), Zero.{u2} (α i)] [_inst_2 : forall (i : ι), Preorder.{u2} (α i)] (r : ι -> ι -> Prop) [_inst_3 : IsStrictOrder.{u1} ι r] {x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)} {y : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)}, (LT.lt.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (Preorder.toLT.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (Dfinsupp.instPreorderDfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) (fun (i : ι) => _inst_2 i))) x y) -> (Exists.{succ u1} ι (fun (i : ι) => And (forall (j : ι), (r j i) -> (And (LE.le.{u2} ((fun (i : ι) => (fun (i : ι) => α i) i) j) (Preorder.toLE.{u2} ((fun (i : ι) => (fun (i : ι) => α i) i) j) (_inst_2 j)) (FunLike.coe.{max (succ u1) (succ u2), succ u1, succ u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) ι (fun (_x : ι) => (fun (i : ι) => (fun (i : ι) => α i) i) _x) (Dfinsupp.funLike.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) x j) (FunLike.coe.{max (succ u1) (succ u2), succ u1, succ u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) ι (fun (_x : ι) => (fun (i : ι) => (fun (i : ι) => α i) i) _x) (Dfinsupp.funLike.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) y j)) (LE.le.{u2} ((fun (i : ι) => (fun (i : ι) => α i) i) j) (Preorder.toLE.{u2} ((fun (i : ι) => (fun (i : ι) => α i) i) j) (_inst_2 j)) (FunLike.coe.{max (succ u1) (succ u2), succ u1, succ u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) ι (fun (_x : ι) => (fun (i : ι) => (fun (i : ι) => α i) i) _x) (Dfinsupp.funLike.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) y j) (FunLike.coe.{max (succ u1) (succ u2), succ u1, succ u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) ι (fun (_x : ι) => (fun (i : ι) => (fun (i : ι) => α i) i) _x) (Dfinsupp.funLike.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) x j)))) (LT.lt.{u2} ((fun (i : ι) => (fun (i : ι) => α i) i) i) (Preorder.toLT.{u2} ((fun (i : ι) => (fun (i : ι) => α i) i) i) (_inst_2 i)) (FunLike.coe.{max (succ u1) (succ u2), succ u1, succ u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) ι (fun (_x : ι) => (fun (i : ι) => (fun (i : ι) => α i) i) _x) (Dfinsupp.funLike.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) x i) (FunLike.coe.{max (succ u1) (succ u2), succ u1, succ u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) ι (fun (_x : ι) => (fun (i : ι) => (fun (i : ι) => α i) i) _x) (Dfinsupp.funLike.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) y i))))
Case conversion may be inaccurate. Consider using '#align dfinsupp.lex_lt_of_lt_of_preorder Dfinsupp.lex_lt_of_lt_of_preorderₓ'. -/
theorem lex_lt_of_lt_of_preorder [∀ i, Preorder (α i)] (r) [IsStrictOrder ι r] {x y : Π₀ i, α i}
    (hlt : x < y) : ∃ i, (∀ j, r j i → x j ≤ y j ∧ y j ≤ x j) ∧ x i < y i :=
  by
  obtain ⟨hle, j, hlt⟩ := Pi.lt_def.1 hlt
  classical
    have : (x.ne_locus y : Set ι).WellFoundedOn r := (x.ne_locus y).finite_toSet.WellFoundedOn
    obtain ⟨i, hi, hl⟩ := this.has_min { i | x i < y i } ⟨⟨j, mem_ne_locus.2 hlt.ne⟩, hlt⟩
    exact
      ⟨i, fun k hk =>
        ⟨hle k,
          of_not_not fun h =>
            hl ⟨k, mem_ne_locus.2 (ne_of_not_le h).symm⟩ ((hle k).lt_of_not_le h) hk⟩,
        hi⟩
#align dfinsupp.lex_lt_of_lt_of_preorder Dfinsupp.lex_lt_of_lt_of_preorder

/- warning: dfinsupp.lex_lt_of_lt -> Dfinsupp.lex_lt_of_lt is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : forall (i : ι), Zero.{u2} (α i)] [_inst_2 : forall (i : ι), PartialOrder.{u2} (α i)] (r : ι -> ι -> Prop) [_inst_3 : IsStrictOrder.{u1} ι r] {x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)} {y : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)}, (LT.lt.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (Preorder.toLT.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (Dfinsupp.preorder.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) (fun (i : ι) => PartialOrder.toPreorder.{u2} (α i) (_inst_2 i)))) x y) -> (Pi.Lex.{u1, u2} ι (fun (i : ι) => α i) r (fun (i : ι) => LT.lt.{u2} (α i) (Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (_inst_2 i)))) (coeFn.{succ (max u1 u2), max (succ u1) (succ u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (fun (_x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => forall (i : ι), α i) (Dfinsupp.hasCoeToFun.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) x) (coeFn.{succ (max u1 u2), max (succ u1) (succ u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (fun (_x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => forall (i : ι), α i) (Dfinsupp.hasCoeToFun.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) y))
but is expected to have type
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : forall (i : ι), Zero.{u2} (α i)] [_inst_2 : forall (i : ι), PartialOrder.{u2} (α i)] (r : ι -> ι -> Prop) [_inst_3 : IsStrictOrder.{u1} ι r] {x : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)} {y : Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)}, (LT.lt.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (Preorder.toLT.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (Dfinsupp.instPreorderDfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) (fun (i : ι) => PartialOrder.toPreorder.{u2} (α i) (_inst_2 i)))) x y) -> (Pi.Lex.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => (fun (i : ι) => α i) i) i) r (fun {i : ι} (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.715 : (fun (i : ι) => (fun (i : ι) => α i) i) i) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.717 : (fun (i : ι) => (fun (i : ι) => α i) i) i) => LT.lt.{u2} ((fun (i : ι) => (fun (i : ι) => α i) i) i) (Preorder.toLT.{u2} ((fun (i : ι) => (fun (i : ι) => α i) i) i) (PartialOrder.toPreorder.{u2} ((fun (i : ι) => (fun (i : ι) => α i) i) i) (_inst_2 i))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.715 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.717) (FunLike.coe.{max (succ u1) (succ u2), succ u1, succ u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) ι (fun (_x : ι) => (fun (i : ι) => (fun (i : ι) => α i) i) _x) (Dfinsupp.funLike.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) x) (FunLike.coe.{max (succ u1) (succ u2), succ u1, succ u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) ι (fun (_x : ι) => (fun (i : ι) => (fun (i : ι) => α i) i) _x) (Dfinsupp.funLike.{u1, u2} ι (fun (i : ι) => (fun (i : ι) => α i) i) (fun (i : ι) => (fun (i : ι) => _inst_1 i) i)) y))
Case conversion may be inaccurate. Consider using '#align dfinsupp.lex_lt_of_lt Dfinsupp.lex_lt_of_ltₓ'. -/
theorem lex_lt_of_lt [∀ i, PartialOrder (α i)] (r) [IsStrictOrder ι r] {x y : Π₀ i, α i}
    (hlt : x < y) : Pi.Lex r (fun i => (· < ·)) x y :=
  by
  simp_rw [Pi.Lex, le_antisymm_iff]
  exact lex_lt_of_lt_of_preorder r hlt
#align dfinsupp.lex_lt_of_lt Dfinsupp.lex_lt_of_lt

/- warning: dfinsupp.lex.is_strict_order -> Dfinsupp.Lex.isStrictOrder is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : forall (i : ι), Zero.{u2} (α i)] [_inst_2 : LinearOrder.{u1} ι] [_inst_3 : forall (i : ι), PartialOrder.{u2} (α i)], IsStrictOrder.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) (LT.lt.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) (Dfinsupp.Lex.hasLt.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) (Preorder.toLT.{u1} ι (PartialOrder.toPreorder.{u1} ι (SemilatticeInf.toPartialOrder.{u1} ι (Lattice.toSemilatticeInf.{u1} ι (LinearOrder.toLattice.{u1} ι _inst_2))))) (fun (i : ι) => Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (_inst_3 i)))))
but is expected to have type
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : forall (i : ι), Zero.{u2} (α i)] [_inst_2 : LinearOrder.{u1} ι] [_inst_3 : forall (i : ι), PartialOrder.{u2} (α i)], IsStrictOrder.{max u2 u1} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.802 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.804 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) => LT.lt.{max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) (Dfinsupp.instLTLexDfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) (Preorder.toLT.{u1} ι (PartialOrder.toPreorder.{u1} ι (SemilatticeInf.toPartialOrder.{u1} ι (Lattice.toSemilatticeInf.{u1} ι (DistribLattice.toLattice.{u1} ι (instDistribLattice.{u1} ι _inst_2)))))) (fun (i : ι) => Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (_inst_3 i)))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.802 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.804)
Case conversion may be inaccurate. Consider using '#align dfinsupp.lex.is_strict_order Dfinsupp.Lex.isStrictOrderₓ'. -/
instance Lex.isStrictOrder [LinearOrder ι] [∀ i, PartialOrder (α i)] :
    IsStrictOrder (Lex (Π₀ i, α i)) (· < ·) :=
  let i : IsStrictOrder (Lex (∀ i, α i)) (· < ·) := Pi.Lex.isStrictOrder
  { irrefl := toLex.Surjective.forall.2 fun a => @irrefl _ _ i.to_isIrrefl a
    trans := toLex.Surjective.forall₃.2 fun a b c => @trans _ _ i.to_isTrans a b c }
#align dfinsupp.lex.is_strict_order Dfinsupp.Lex.isStrictOrder

variable [LinearOrder ι]

#print Dfinsupp.Lex.partialOrder /-
/-- The partial order on `dfinsupp`s obtained by the lexicographic ordering.
See `dfinsupp.lex.linear_order` for a proof that this partial order is in fact linear. -/
instance Lex.partialOrder [∀ i, PartialOrder (α i)] : PartialOrder (Lex (Π₀ i, α i)) :=
  PartialOrder.lift (fun x => toLex ⇑(ofLex x)) Dfinsupp.coeFn_injective
#align dfinsupp.lex.partial_order Dfinsupp.Lex.partialOrder
-/

section LinearOrder

variable [∀ i, LinearOrder (α i)]

/-- Auxiliary helper to case split computably. There is no need for this to be public, as it
can be written with `or.by_cases` on `lt_trichotomy` once the instances below are constructed. -/
private def lt_trichotomy_rec {P : Lex (Π₀ i, α i) → Lex (Π₀ i, α i) → Sort _}
    (h_lt : ∀ {f g}, toLex f < toLex g → P (toLex f) (toLex g))
    (h_eq : ∀ {f g}, toLex f = toLex g → P (toLex f) (toLex g))
    (h_gt : ∀ {f g}, toLex g < toLex f → P (toLex f) (toLex g)) : ∀ f g, P f g :=
  Lex.rec fun f =>
    Lex.rec fun g =>
      match (motive := ∀ y, (f.neLocus g).min = y → _) _, rfl with
      | ⊤, h => h_eq (neLocus_eq_empty.mp <| Finset.min_eq_top.mp h)
      | (wit : ι), h =>
        (mem_neLocus.mp <| Finset.mem_of_min h).lt_or_lt.byCases
          (fun hwit =>
            h_lt ⟨wit, fun j hj => not_mem_neLocus.mp (Finset.not_mem_of_lt_min hj h), hwit⟩)
          fun hwit =>
          h_gt
            ⟨wit, fun j hj =>
              not_mem_neLocus.mp (Finset.not_mem_of_lt_min hj <| by rwa [ne_locus_comm]), hwit⟩
#align dfinsupp.lt_trichotomy_rec dfinsupp.lt_trichotomy_rec

/- ./././Mathport/Syntax/Translate/Command.lean:317:38: unsupported irreducible non-definition -/
#print Dfinsupp.Lex.decidableLE /-
irreducible_def Lex.decidableLE : @DecidableRel (Lex (Π₀ i, α i)) (· ≤ ·) :=
  ltTrichotomyRec (fun f g h => isTrue <| Or.inr h) (fun f g h => isTrue <| Or.inl <| congr_arg _ h)
    fun f g h => isFalse fun h' => (lt_irrefl _ (h.trans_le h')).elim
#align dfinsupp.lex.decidable_le Dfinsupp.Lex.decidableLE
-/

/- warning: dfinsupp.lex.decidable_lt -> Dfinsupp.Lex.decidableLT is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : forall (i : ι), Zero.{u2} (α i)] [_inst_2 : LinearOrder.{u1} ι] [_inst_3 : forall (i : ι), LinearOrder.{u2} (α i)], DecidableRel.{succ (max u1 u2)} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) (LT.lt.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) (Dfinsupp.Lex.hasLt.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) (Preorder.toLT.{u1} ι (PartialOrder.toPreorder.{u1} ι (SemilatticeInf.toPartialOrder.{u1} ι (Lattice.toSemilatticeInf.{u1} ι (LinearOrder.toLattice.{u1} ι _inst_2))))) (fun (i : ι) => Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (LinearOrder.toLattice.{u2} (α i) (_inst_3 i))))))))
but is expected to have type
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : forall (i : ι), Zero.{u2} (α i)] [_inst_2 : LinearOrder.{u1} ι] [_inst_3 : forall (i : ι), LinearOrder.{u2} (α i)], DecidableRel.{succ (max u2 u1)} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.1706 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.1708 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) => LT.lt.{max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) (Dfinsupp.instLTLexDfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) (Preorder.toLT.{u1} ι (PartialOrder.toPreorder.{u1} ι (SemilatticeInf.toPartialOrder.{u1} ι (Lattice.toSemilatticeInf.{u1} ι (DistribLattice.toLattice.{u1} ι (instDistribLattice.{u1} ι _inst_2)))))) (fun (i : ι) => Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (DistribLattice.toLattice.{u2} (α i) (instDistribLattice.{u2} (α i) (_inst_3 i)))))))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.1706 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.1708)
Case conversion may be inaccurate. Consider using '#align dfinsupp.lex.decidable_lt Dfinsupp.Lex.decidableLTₓ'. -/
/- ./././Mathport/Syntax/Translate/Command.lean:317:38: unsupported irreducible non-definition -/
irreducible_def Lex.decidableLT : @DecidableRel (Lex (Π₀ i, α i)) (· < ·) :=
  ltTrichotomyRec (fun f g h => isTrue h) (fun f g h => isFalse h.not_lt) fun f g h =>
    isFalse h.asymm
#align dfinsupp.lex.decidable_lt Dfinsupp.Lex.decidableLT

#print Dfinsupp.Lex.linearOrder /-
/-- The linear order on `dfinsupp`s obtained by the lexicographic ordering. -/
instance Lex.linearOrder : LinearOrder (Lex (Π₀ i, α i)) :=
  {
    Lex.partialOrder with
    le_total :=
      ltTrichotomyRec (fun f g h => Or.inl h.le) (fun f g h => Or.inl h.le) fun f g h => Or.inr h.le
    decidableLt := by infer_instance
    decidableLe := by infer_instance
    DecidableEq := by infer_instance }
#align dfinsupp.lex.linear_order Dfinsupp.Lex.linearOrder
-/

end LinearOrder

variable [∀ i, PartialOrder (α i)]

/- warning: dfinsupp.to_lex_monotone -> Dfinsupp.toLex_monotone is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : forall (i : ι), Zero.{u2} (α i)] [_inst_2 : LinearOrder.{u1} ι] [_inst_3 : forall (i : ι), PartialOrder.{u2} (α i)], Monotone.{max u1 u2, max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) (Dfinsupp.preorder.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) (fun (i : ι) => PartialOrder.toPreorder.{u2} (α i) (_inst_3 i))) (PartialOrder.toPreorder.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) (Dfinsupp.Lex.partialOrder.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) _inst_2 (fun (i : ι) => _inst_3 i))) (coeFn.{succ (max u1 u2), succ (max u1 u2)} (Equiv.{succ (max u1 u2), succ (max u1 u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)))) (fun (_x : Equiv.{succ (max u1 u2), succ (max u1 u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)))) => (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) -> (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)))) (Equiv.hasCoeToFun.{succ (max u1 u2), succ (max u1 u2)} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)))) (toLex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))))
but is expected to have type
  forall {ι : Type.{u2}} {α : ι -> Type.{u1}} [_inst_1 : forall (i : ι), Zero.{u1} (α i)] [_inst_2 : LinearOrder.{u2} ι] [_inst_3 : forall (i : ι), PartialOrder.{u1} (α i)], Monotone.{max u2 u1, max u2 u1} (Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (Lex.{max u1 u2} (Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) (Dfinsupp.instPreorderDfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) (fun (i : ι) => PartialOrder.toPreorder.{u1} (α i) (_inst_3 i))) (PartialOrder.toPreorder.{max u2 u1} (Lex.{max u1 u2} (Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) (Dfinsupp.Lex.partialOrder.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i) _inst_2 (fun (i : ι) => _inst_3 i))) (FunLike.coe.{max (succ u2) (succ u1), max (succ u2) (succ u1), max (succ u2) (succ u1)} (Equiv.{succ (max u1 u2), succ (max u1 u2)} (Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (Lex.{max u1 u2} (Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)))) (Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (fun (_x : Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => (fun (x._@.Mathlib.Logic.Equiv.Defs._hyg.808 : Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) => Lex.{max u1 u2} (Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))) _x) (Equiv.instFunLikeEquiv.{max (succ u2) (succ u1), max (succ u2) (succ u1)} (Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)) (Lex.{max u1 u2} (Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i)))) (toLex.{max u1 u2} (Dfinsupp.{u2, u1} ι (fun (i : ι) => α i) (fun (i : ι) => _inst_1 i))))
Case conversion may be inaccurate. Consider using '#align dfinsupp.to_lex_monotone Dfinsupp.toLex_monotoneₓ'. -/
theorem toLex_monotone : Monotone (@toLex (Π₀ i, α i)) := fun a b h =>
  le_of_lt_or_eq <|
    or_iff_not_imp_right.2 fun hne => by
      classical exact
          ⟨Finset.min' _ (nonempty_ne_locus_iff.2 hne), fun j hj =>
            not_mem_ne_locus.1 fun h => (Finset.min'_le _ _ h).not_lt hj,
            (h _).lt_of_ne (mem_ne_locus.1 <| Finset.min'_mem _ _)⟩
#align dfinsupp.to_lex_monotone Dfinsupp.toLex_monotone

#print Dfinsupp.lt_of_forall_lt_of_lt /-
theorem lt_of_forall_lt_of_lt (a b : Lex (Π₀ i, α i)) (i : ι) :
    (∀ j < i, ofLex a j = ofLex b j) → ofLex a i < ofLex b i → a < b := fun h1 h2 => ⟨i, h1, h2⟩
#align dfinsupp.lt_of_forall_lt_of_lt Dfinsupp.lt_of_forall_lt_of_lt
-/

end Zero

section Covariants

variable [LinearOrder ι] [∀ i, AddMonoid (α i)] [∀ i, LinearOrder (α i)]

/-!  We are about to sneak in a hypothesis that might appear to be too strong.
We assume `covariant_class` with *strict* inequality `<` also when proving the one with the
*weak* inequality `≤`.  This is actually necessary: addition on `lex (Π₀ i, α i)` may fail to be
monotone, when it is "just" monotone on `α i`. -/

section Left

variable [∀ i, CovariantClass (α i) (α i) (· + ·) (· < ·)]

/- warning: dfinsupp.lex.covariant_class_lt_left -> Dfinsupp.Lex.covariantClass_lt_left is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : LinearOrder.{u1} ι] [_inst_2 : forall (i : ι), AddMonoid.{u2} (α i)] [_inst_3 : forall (i : ι), LinearOrder.{u2} (α i)] [_inst_4 : forall (i : ι), CovariantClass.{u2, u2} (α i) (α i) (HAdd.hAdd.{u2, u2, u2} (α i) (α i) (α i) (instHAdd.{u2} (α i) (AddZeroClass.toHasAdd.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (LT.lt.{u2} (α i) (Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (LinearOrder.toLattice.{u2} (α i) (_inst_3 i)))))))], CovariantClass.{max u1 u2, max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (instHAdd.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.hasAdd.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i)))) (Dfinsupp.hasAdd.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i)))))) (LT.lt.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Dfinsupp.Lex.hasLt.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))) (Preorder.toLT.{u1} ι (PartialOrder.toPreorder.{u1} ι (SemilatticeInf.toPartialOrder.{u1} ι (Lattice.toSemilatticeInf.{u1} ι (LinearOrder.toLattice.{u1} ι _inst_1))))) (fun (i : ι) => Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (LinearOrder.toLattice.{u2} (α i) (_inst_3 i))))))))
but is expected to have type
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : LinearOrder.{u1} ι] [_inst_2 : forall (i : ι), AddMonoid.{u2} (α i)] [_inst_3 : forall (i : ι), LinearOrder.{u2} (α i)] [_inst_4 : forall (i : ι), CovariantClass.{u2, u2} (α i) (α i) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2680 : α i) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2682 : α i) => HAdd.hAdd.{u2, u2, u2} (α i) (α i) (α i) (instHAdd.{u2} (α i) (AddZeroClass.toAdd.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i)))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2680 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2682) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2695 : α i) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2697 : α i) => LT.lt.{u2} (α i) (Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (DistribLattice.toLattice.{u2} (α i) (instDistribLattice.{u2} (α i) (_inst_3 i))))))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2695 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2697)], CovariantClass.{max u2 u1, max u2 u1} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2757 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2759 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) => HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (instHAdd.{max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (instAddLex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i))) (Dfinsupp.instAddDfinsuppToZero.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2757 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2759) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2772 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2774 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) => LT.lt.{max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Dfinsupp.instLTLexDfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)) (Preorder.toLT.{u1} ι (PartialOrder.toPreorder.{u1} ι (SemilatticeInf.toPartialOrder.{u1} ι (Lattice.toSemilatticeInf.{u1} ι (DistribLattice.toLattice.{u1} ι (instDistribLattice.{u1} ι _inst_1)))))) (fun (i : ι) => Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (DistribLattice.toLattice.{u2} (α i) (instDistribLattice.{u2} (α i) (_inst_3 i)))))))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2772 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2774)
Case conversion may be inaccurate. Consider using '#align dfinsupp.lex.covariant_class_lt_left Dfinsupp.Lex.covariantClass_lt_leftₓ'. -/
instance Lex.covariantClass_lt_left :
    CovariantClass (Lex (Π₀ i, α i)) (Lex (Π₀ i, α i)) (· + ·) (· < ·) :=
  ⟨fun f g h ⟨a, lta, ha⟩ =>
    ⟨a, fun j ja => congr_arg ((· + ·) _) (lta j ja), add_lt_add_left ha _⟩⟩
#align dfinsupp.lex.covariant_class_lt_left Dfinsupp.Lex.covariantClass_lt_left

/- warning: dfinsupp.lex.covariant_class_le_left -> Dfinsupp.Lex.covariantClass_le_left is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : LinearOrder.{u1} ι] [_inst_2 : forall (i : ι), AddMonoid.{u2} (α i)] [_inst_3 : forall (i : ι), LinearOrder.{u2} (α i)] [_inst_4 : forall (i : ι), CovariantClass.{u2, u2} (α i) (α i) (HAdd.hAdd.{u2, u2, u2} (α i) (α i) (α i) (instHAdd.{u2} (α i) (AddZeroClass.toHasAdd.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (LT.lt.{u2} (α i) (Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (LinearOrder.toLattice.{u2} (α i) (_inst_3 i)))))))], CovariantClass.{max u1 u2, max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (instHAdd.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.hasAdd.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i)))) (Dfinsupp.hasAdd.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i)))))) (LE.le.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Preorder.toLE.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (PartialOrder.toPreorder.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Dfinsupp.Lex.partialOrder.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))) _inst_1 (fun (i : ι) => SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (LinearOrder.toLattice.{u2} (α i) (_inst_3 i))))))))
but is expected to have type
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : LinearOrder.{u1} ι] [_inst_2 : forall (i : ι), AddMonoid.{u2} (α i)] [_inst_3 : forall (i : ι), LinearOrder.{u2} (α i)] [_inst_4 : forall (i : ι), CovariantClass.{u2, u2} (α i) (α i) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2884 : α i) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2886 : α i) => HAdd.hAdd.{u2, u2, u2} (α i) (α i) (α i) (instHAdd.{u2} (α i) (AddZeroClass.toAdd.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i)))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2884 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2886) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2899 : α i) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2901 : α i) => LT.lt.{u2} (α i) (Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (DistribLattice.toLattice.{u2} (α i) (instDistribLattice.{u2} (α i) (_inst_3 i))))))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2899 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2901)], CovariantClass.{max u2 u1, max u2 u1} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2961 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2963 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) => HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (instHAdd.{max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (instAddLex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i))) (Dfinsupp.instAddDfinsuppToZero.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2961 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2963) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2976 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2978 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) => LE.le.{max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Preorder.toLE.{max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (PartialOrder.toPreorder.{max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Dfinsupp.Lex.partialOrder.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)) _inst_1 (fun (i : ι) => SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (DistribLattice.toLattice.{u2} (α i) (instDistribLattice.{u2} (α i) (_inst_3 i)))))))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2976 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.2978)
Case conversion may be inaccurate. Consider using '#align dfinsupp.lex.covariant_class_le_left Dfinsupp.Lex.covariantClass_le_leftₓ'. -/
instance Lex.covariantClass_le_left :
    CovariantClass (Lex (Π₀ i, α i)) (Lex (Π₀ i, α i)) (· + ·) (· ≤ ·) :=
  Add.to_covariantClass_left _
#align dfinsupp.lex.covariant_class_le_left Dfinsupp.Lex.covariantClass_le_left

end Left

section Right

variable [∀ i, CovariantClass (α i) (α i) (Function.swap (· + ·)) (· < ·)]

/- warning: dfinsupp.lex.covariant_class_lt_right -> Dfinsupp.Lex.covariantClass_lt_right is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : LinearOrder.{u1} ι] [_inst_2 : forall (i : ι), AddMonoid.{u2} (α i)] [_inst_3 : forall (i : ι), LinearOrder.{u2} (α i)] [_inst_4 : forall (i : ι), CovariantClass.{u2, u2} (α i) (α i) (Function.swap.{succ u2, succ u2, succ u2} (α i) (α i) (fun (ᾰ : α i) (ᾰ : α i) => α i) (HAdd.hAdd.{u2, u2, u2} (α i) (α i) (α i) (instHAdd.{u2} (α i) (AddZeroClass.toHasAdd.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i)))))) (LT.lt.{u2} (α i) (Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (LinearOrder.toLattice.{u2} (α i) (_inst_3 i)))))))], CovariantClass.{max u1 u2, max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Function.swap.{succ (max u1 u2), succ (max u1 u2), succ (max u1 u2)} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (fun (ᾰ : Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (ᾰ : Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) => Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (instHAdd.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.hasAdd.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i)))) (Dfinsupp.hasAdd.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))))) (LT.lt.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Dfinsupp.Lex.hasLt.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))) (Preorder.toLT.{u1} ι (PartialOrder.toPreorder.{u1} ι (SemilatticeInf.toPartialOrder.{u1} ι (Lattice.toSemilatticeInf.{u1} ι (LinearOrder.toLattice.{u1} ι _inst_1))))) (fun (i : ι) => Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (LinearOrder.toLattice.{u2} (α i) (_inst_3 i))))))))
but is expected to have type
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : LinearOrder.{u1} ι] [_inst_2 : forall (i : ι), AddMonoid.{u2} (α i)] [_inst_3 : forall (i : ι), LinearOrder.{u2} (α i)] [_inst_4 : forall (i : ι), CovariantClass.{u2, u2} (α i) (α i) (Function.swap.{succ u2, succ u2, succ u2} (α i) (α i) (fun (ᾰ : α i) (ᾰ : α i) => α i) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3115 : α i) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3117 : α i) => HAdd.hAdd.{u2, u2, u2} (α i) (α i) (α i) (instHAdd.{u2} (α i) (AddZeroClass.toAdd.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i)))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3115 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3117)) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3130 : α i) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3132 : α i) => LT.lt.{u2} (α i) (Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (DistribLattice.toLattice.{u2} (α i) (instDistribLattice.{u2} (α i) (_inst_3 i))))))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3130 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3132)], CovariantClass.{max u2 u1, max u2 u1} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Function.swap.{max (succ u1) (succ u2), max (succ u1) (succ u2), max (succ u1) (succ u2)} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (fun (ᾰ : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (ᾰ : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) => Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3195 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3197 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) => HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (instHAdd.{max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (instAddLex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i))) (Dfinsupp.instAddDfinsuppToZero.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3195 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3197)) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3210 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3212 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) => LT.lt.{max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Dfinsupp.instLTLexDfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)) (Preorder.toLT.{u1} ι (PartialOrder.toPreorder.{u1} ι (SemilatticeInf.toPartialOrder.{u1} ι (Lattice.toSemilatticeInf.{u1} ι (DistribLattice.toLattice.{u1} ι (instDistribLattice.{u1} ι _inst_1)))))) (fun (i : ι) => Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (DistribLattice.toLattice.{u2} (α i) (instDistribLattice.{u2} (α i) (_inst_3 i)))))))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3210 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3212)
Case conversion may be inaccurate. Consider using '#align dfinsupp.lex.covariant_class_lt_right Dfinsupp.Lex.covariantClass_lt_rightₓ'. -/
instance Lex.covariantClass_lt_right :
    CovariantClass (Lex (Π₀ i, α i)) (Lex (Π₀ i, α i)) (Function.swap (· + ·)) (· < ·) :=
  ⟨fun f g h ⟨a, lta, ha⟩ =>
    ⟨a, fun j ja => congr_arg (· + ofLex f j) (lta j ja), add_lt_add_right ha _⟩⟩
#align dfinsupp.lex.covariant_class_lt_right Dfinsupp.Lex.covariantClass_lt_right

/- warning: dfinsupp.lex.covariant_class_le_right -> Dfinsupp.Lex.covariantClass_le_right is a dubious translation:
lean 3 declaration is
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : LinearOrder.{u1} ι] [_inst_2 : forall (i : ι), AddMonoid.{u2} (α i)] [_inst_3 : forall (i : ι), LinearOrder.{u2} (α i)] [_inst_4 : forall (i : ι), CovariantClass.{u2, u2} (α i) (α i) (Function.swap.{succ u2, succ u2, succ u2} (α i) (α i) (fun (ᾰ : α i) (ᾰ : α i) => α i) (HAdd.hAdd.{u2, u2, u2} (α i) (α i) (α i) (instHAdd.{u2} (α i) (AddZeroClass.toHasAdd.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i)))))) (LT.lt.{u2} (α i) (Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (LinearOrder.toLattice.{u2} (α i) (_inst_3 i)))))))], CovariantClass.{max u1 u2, max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Function.swap.{succ (max u1 u2), succ (max u1 u2), succ (max u1 u2)} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (fun (ᾰ : Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (ᾰ : Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) => Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (instHAdd.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Lex.hasAdd.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i)))) (Dfinsupp.hasAdd.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))))) (LE.le.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Preorder.toLE.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (PartialOrder.toPreorder.{max u1 u2} (Lex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) (Dfinsupp.Lex.partialOrder.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddZeroClass.toHasZero.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))) _inst_1 (fun (i : ι) => SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (LinearOrder.toLattice.{u2} (α i) (_inst_3 i))))))))
but is expected to have type
  forall {ι : Type.{u1}} {α : ι -> Type.{u2}} [_inst_1 : LinearOrder.{u1} ι] [_inst_2 : forall (i : ι), AddMonoid.{u2} (α i)] [_inst_3 : forall (i : ι), LinearOrder.{u2} (α i)] [_inst_4 : forall (i : ι), CovariantClass.{u2, u2} (α i) (α i) (Function.swap.{succ u2, succ u2, succ u2} (α i) (α i) (fun (ᾰ : α i) (ᾰ : α i) => α i) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3339 : α i) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3341 : α i) => HAdd.hAdd.{u2, u2, u2} (α i) (α i) (α i) (instHAdd.{u2} (α i) (AddZeroClass.toAdd.{u2} (α i) (AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i)))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3339 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3341)) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3354 : α i) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3356 : α i) => LT.lt.{u2} (α i) (Preorder.toLT.{u2} (α i) (PartialOrder.toPreorder.{u2} (α i) (SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (DistribLattice.toLattice.{u2} (α i) (instDistribLattice.{u2} (α i) (_inst_3 i))))))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3354 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3356)], CovariantClass.{max u2 u1, max u2 u1} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Function.swap.{max (succ u1) (succ u2), max (succ u1) (succ u2), max (succ u1) (succ u2)} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (fun (ᾰ : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (ᾰ : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) => Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3419 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3421 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) => HAdd.hAdd.{max u1 u2, max u1 u2, max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (instHAdd.{max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (instAddLex.{max u1 u2} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i))) (Dfinsupp.instAddDfinsuppToZero.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toAddZeroClass.{u2} (α i) (_inst_2 i))))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3419 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3421)) (fun (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3434 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3436 : Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) => LE.le.{max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Preorder.toLE.{max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (PartialOrder.toPreorder.{max u1 u2} (Lex.{max u2 u1} (Dfinsupp.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)))) (Dfinsupp.Lex.partialOrder.{u1, u2} ι (fun (i : ι) => α i) (fun (i : ι) => AddMonoid.toZero.{u2} ((fun (i : ι) => α i) i) (_inst_2 i)) _inst_1 (fun (i : ι) => SemilatticeInf.toPartialOrder.{u2} (α i) (Lattice.toSemilatticeInf.{u2} (α i) (DistribLattice.toLattice.{u2} (α i) (instDistribLattice.{u2} (α i) (_inst_3 i)))))))) x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3434 x._@.Mathlib.Data.Dfinsupp.Lex._hyg.3436)
Case conversion may be inaccurate. Consider using '#align dfinsupp.lex.covariant_class_le_right Dfinsupp.Lex.covariantClass_le_rightₓ'. -/
instance Lex.covariantClass_le_right :
    CovariantClass (Lex (Π₀ i, α i)) (Lex (Π₀ i, α i)) (Function.swap (· + ·)) (· ≤ ·) :=
  Add.to_covariantClass_right _
#align dfinsupp.lex.covariant_class_le_right Dfinsupp.Lex.covariantClass_le_right

end Right

end Covariants

end Dfinsupp


import data.fin
import tactic

-- This does exist in mathlib
lemma fin_zero_le_any_val (n : ℕ) : ∀ i : fin (n + 2), 0 ≤ i :=
begin
    intro i,
    have j0 : 0 < n + 1 + 1, linarith,
    have j0 := @fin.coe_val_of_lt (n+1) 0 j0,
    have h3 : 0 ≤ i.val, linarith,
    apply fin.le_iff_val_le_val.mpr,
    rw ← j0 at h3,
    exact h3,
end

lemma fin_zero_le_any_val_v1 (n : ℕ) (i : fin (n + 1)) : 0 ≤ i :=
fin.le_iff_val_le_val.mpr $ nat.zero_le _

-- This exists in mathlib, but in a form that is not immediately useful
lemma fin_le_last_val (n : ℕ) (i : fin (n + 2)) :  i ≤ (n+1) :=
begin
    have j0 : n + 1 < n + 1 + 1, linarith,
    have j0 := @fin.coe_val_of_lt (n+1) (n+1) j0,
    have h3 : i.val ≤ n + 1, linarith [i.is_lt],
    apply fin.le_iff_val_le_val.mpr,
    rw ← j0 at h3,
    exact h3,
end

lemma fin_le_last_val_v1 (n : ℕ) (i : fin (n + 1)) : i ≤ n :=
fin.le_iff_val_le_val.mpr $ (fin.coe_val_of_lt $ nat.lt_succ_self n).symm ▸ nat.le_of_lt_succ i.2

lemma fin_le_last_val_v2 (n : ℕ) : ∀ i : fin (n + 2), i ≤ (n+1) :=
begin
  intro i,
  change i.val ≤ ((_ + _) : fin (n+2)).val,
  norm_cast,
  have := i.2,
  rw fin.coe_val_of_lt; omega
end

-- Another version with a better name from Y. Pechersky
lemma fin.le_coe_last {n : ℕ} (i : fin (n + 1)) : i ≤ n :=
begin
  rw [fin.le_def, <-nat.lt_succ_iff, fin.coe_val_of_lt (lt_add_one n)],
  exact i.is_lt,
end

/- I'd also like to obtain the result this way

lemma fin_le_last_val_v3 (n : ℕ) (i : fin (n + 1)) : i ≤ n :=
begin
  have h1 := fin.le_last i,
  have h01 := @fin.coe_last n,
  have h2 := fin.last_val n,
  have h3 := (fin.le_iff_val_le_val).mp h1,
  rw h2 at h3,
  obtain ⟨i, hi ⟩ := i, sorry
end

example {n : ℕ} (i j : fin n) (h : i < j) :
  n = ↑i + (↑j - ↑i + 1 + (n - 1 - ↑j)) :=
begin
  cases i,
  cases j,
  dsimp,
  change i_val < j_val at h,
  omega, done
end

-/

-- This is very particular, only needed in my own proof
-- This is courtesy Shing Tak Lam
lemma shing (n : ℕ) (i j : fin (n+1)) (h : (j.val : fin (n+2)) < (i.val.succ : fin (n+2))) :
    j.val < i.val.succ :=
begin
  change (j.val : fin (n+2)).val < (i.val.succ : fin (n+2)).val at h,
  rwa [fin.coe_val_of_lt (show j.1 < n + 2, by linarith [j.2]),
       fin.coe_val_of_lt (show i.1 + 1 < n + 2, by linarith [i.2])] at h,
end

-- Again thanks to Shing Tak Lam
lemma fin_lt_succ (n : ℕ) (i : fin (n + 1)) : (i : fin (n+2)) < (i+1) :=
begin
  cases i with i hi,
  change (_ : fin (n+2)).val < (_ : fin (n+2)).val,
  simp only [fin.coe_mk, coe_coe],
  norm_cast,
  rw [fin.coe_val_of_lt, fin.coe_val_of_lt]; omega,
end

-- Some `fin` lemmas from Y. Pechersky
lemma fin.coe_succ_eq_succ {n : ℕ} (i : fin n) : ((i : fin (n + 1)) + 1) = i.succ :=
begin
  rw [fin.eq_iff_veq, fin.succ_val, coe_coe],
  norm_cast,
  apply fin.coe_coe_of_lt,
  exact add_lt_add_right i.is_lt 1
end

lemma fin.coe_eq_cast_succ {n : ℕ} (i : fin n) : (i : fin (n + 1)) = i.cast_succ :=
begin
  rw [fin.cast_succ, fin.cast_add, fin.cast_le, fin.cast_lt],
  obtain ⟨i, hi⟩ := i,
  rw fin.eq_iff_veq,
  have : i.succ = i + 1 := rfl,
  simp only [this],
  apply fin.coe_val_of_lt,
  exact nat.lt.step hi,
end

lemma fin.val_coe_eq_self {n : ℕ} (i : fin n) : (i : fin (n + 1)).val = i.val :=
by { rw fin.coe_eq_cast_succ, refl }

lemma fin.lt_succ {n : ℕ} (i : fin n) : (i : fin (n + 1)) < i.succ :=
begin
  rw [fin.coe_eq_cast_succ, fin.cast_succ, fin.lt_iff_val_lt_val, fin.cast_add_val, fin.succ_val],
  exact lt_add_one i.val
end

lemma fin_lt_succ' (n : ℕ) (i : fin (n + 1)) : (i : fin (n + 2)) < (i + 1) :=
by { rw fin.coe_succ_eq_succ, exact fin.lt_succ _ }

-- Lemmas from Y. Kudryashov
@[simp] lemma mk_zero (n : ℕ) : (⟨0, n.zero_lt_succ⟩ : fin (n + 1)) = 0 := rfl

@[simp] lemma mk_one (n : ℕ) (hn : 1 < n + 1) : (⟨1, hn⟩ : fin (n + 1)) = 1 :=
fin.eq_of_veq (nat.mod_eq_of_lt hn).symm

@[simp] lemma mk_bit0 {m n : ℕ} (h : bit0 m < n) :
  (⟨_, h⟩ : fin n) = bit0 ⟨m, (nat.le_add_right _ _).trans_lt h⟩ :=
fin.eq_of_veq (nat.mod_eq_of_lt h).symm

@[simp] lemma mk_bit1 {m n : ℕ} (h : bit1 m < n + 1) :
  (⟨bit1 m, h⟩ : fin (n + 1)) = bit1 ⟨m, (nat.le_add_right m m).trans_lt
    ((m + m).lt_succ_self.trans h)⟩ :=
begin
  ext,
  simp only [bit1, bit0] at h ⊢,
  simp only [fin.val_add, fin.one_val, ← nat.add_mod, nat.mod_eq_of_lt h]
end


/-
Copyright (c) 2018 Kenny Lau. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Mario Carneiro and Kenny Lau
-/
import Mathlib.PrePort
import Mathlib.Lean3Lib.init.default
import Mathlib.data.int.basic
import Mathlib.data.list.range
import Mathlib.PostPort

namespace Mathlib

namespace int

/-- List enumerating `[m, n)`. -/
def range (m : ℤ) (n : ℤ) : List ℤ := list.map (fun (r : ℕ) => m + ↑r) (list.range (to_nat (n - m)))

theorem mem_range_iff {m : ℤ} {n : ℤ} {r : ℤ} : r ∈ range m n ↔ m ≤ r ∧ r < n := sorry

protected instance decidable_le_lt (P : ℤ → Prop) [decidable_pred P] (m : ℤ) (n : ℤ) :
    Decidable (∀ (r : ℤ), m ≤ r → r < n → P r) :=
  decidable_of_iff (∀ (r : ℤ), r ∈ range m n → P r) sorry

protected instance decidable_le_le (P : ℤ → Prop) [decidable_pred P] (m : ℤ) (n : ℤ) :
    Decidable (∀ (r : ℤ), m ≤ r → r ≤ n → P r) :=
  decidable_of_iff (∀ (r : ℤ), r ∈ range m (n + 1) → P r) sorry

protected instance decidable_lt_lt (P : ℤ → Prop) [decidable_pred P] (m : ℤ) (n : ℤ) :
    Decidable (∀ (r : ℤ), m < r → r < n → P r) :=
  int.decidable_le_lt P (m + 1) n

protected instance decidable_lt_le (P : ℤ → Prop) [decidable_pred P] (m : ℤ) (n : ℤ) :
    Decidable (∀ (r : ℤ), m < r → r ≤ n → P r) :=
  int.decidable_le_le P (m + 1) n

end Mathlib


/-
Copyright (c) 2019 Johannes Hölzl. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Johannes Hölzl, Mario Carneiro
-/
import algebra.order.field.defs
import data.rat.basic
import data.int.cast.lemmas
import tactic.assert_exists

/-!
# Order for Rational Numbers

> THIS FILE IS SYNCHRONIZED WITH MATHLIB4.
> Any changes to this file require a corresponding PR to mathlib4.

## Summary

We define the order on `ℚ`, prove that `ℚ` is a discrete, linearly ordered field, and define
functions such as `abs` and `sqrt` that depend on this order.

## Notations

- `/.` is infix notation for `rat.mk`.

## Tags

rat, rationals, field, ℚ, numerator, denominator, num, denom, order, ordering, sqrt, abs
-/

namespace rat
variables (a b c : ℚ)
open_locale rat

/-- A rational number is called nonnegative if its numerator is nonnegative. -/
protected def nonneg (r : ℚ) : Prop := 0 ≤ r.num

@[simp]

protected lemma nonneg_add {a b} : rat.nonneg a → rat.nonneg b → rat.nonneg (a + b) :=
num_denom_cases_on' a $ λ n₁ d₁ h₁,
num_denom_cases_on' b $ λ n₂ d₂ h₂,
begin
  have d₁0 : 0 < (d₁:ℤ) := int.coe_nat_pos.2 (nat.pos_of_ne_zero h₁),
  have d₂0 : 0 < (d₂:ℤ) := int.coe_nat_pos.2 (nat.pos_of_ne_zero h₂),
  simp [d₁0, d₂0, h₁, h₂, mul_pos d₁0 d₂0],
  intros n₁0 n₂0,
  apply add_nonneg; apply mul_nonneg; {assumption <|> apply int.coe_zero_le},
end

protected lemma nonneg_mul {a b} : rat.nonneg a → rat.nonneg b → rat.nonneg (a * b) :=
num_denom_cases_on' a $ λ n₁ d₁ h₁,
num_denom_cases_on' b $ λ n₂ d₂ h₂,
begin
  have d₁0 : 0 < (d₁:ℤ) := int.coe_nat_pos.2 (nat.pos_of_ne_zero h₁),
  have d₂0 : 0 < (d₂:ℤ) := int.coe_nat_pos.2 (nat.pos_of_ne_zero h₂),
  simp [d₁0, d₂0, h₁, h₂, mul_pos d₁0 d₂0, mul_nonneg] { contextual := tt }
end

protected lemma nonneg_antisymm {a} : rat.nonneg a → rat.nonneg (-a) → a = 0 :=
num_denom_cases_on' a $ λ n d h,
begin
  have d0 : 0 < (d:ℤ) := int.coe_nat_pos.2 (nat.pos_of_ne_zero h),
  simp [d0, h],
  exact λ h₁ h₂, le_antisymm h₂ h₁
end

protected lemma nonneg_total : rat.nonneg a ∨ rat.nonneg (-a) :=
by cases a with n; exact
or.imp_right neg_nonneg_of_nonpos (le_total 0 n)

instance decidable_nonneg : decidable (rat.nonneg a) :=
by cases a; unfold rat.nonneg; apply_instance

/-- Relation `a ≤ b` on `ℚ` defined as `a ≤ b ↔ rat.nonneg (b - a)`. Use `a ≤ b` instead of
`rat.le a b`. -/
protected def le (a b : ℚ) := rat.nonneg (b - a)

instance : has_le ℚ := ⟨rat.le⟩

instance decidable_le : decidable_rel ((≤) : ℚ → ℚ → Prop)
| a b := show decidable (rat.nonneg (b - a)), by apply_instance

protected theorem le_def {a b c d : ℤ} (b0 : 0 < b) (d0 : 0 < d) :
  a /. b ≤ c /. d ↔ a * d ≤ c * b :=
begin
  show rat.nonneg _ ↔ _,
  rw ← sub_nonneg,
  simp [sub_eq_add_neg, ne_of_gt b0, ne_of_gt d0, mul_pos d0 b0]
end

protected theorem le_refl : a ≤ a :=
show rat.nonneg (a - a), by rw sub_self; exact le_refl (0 : ℤ)

protected theorem le_total : a ≤ b ∨ b ≤ a :=
by have := rat.nonneg_total (b - a); rwa neg_sub at this

protected theorem le_antisymm {a b : ℚ} (hab : a ≤ b) (hba : b ≤ a) : a = b :=
by { have := eq_neg_of_add_eq_zero_left (rat.nonneg_antisymm hba $
 by rwa [← sub_eq_add_neg, neg_sub]), rwa neg_neg at this }

protected theorem le_trans {a b c : ℚ} (hab : a ≤ b) (hbc : b ≤ c) : a ≤ c :=
have rat.nonneg (b - a + (c - b)), from rat.nonneg_add hab hbc,
by simpa [sub_eq_add_neg, add_comm, add_left_comm]

instance : linear_order ℚ :=
{ le              := rat.le,
  le_refl         := rat.le_refl,
  le_trans        := @rat.le_trans,
  le_antisymm     := @rat.le_antisymm,
  le_total        := rat.le_total,
  decidable_eq    := by apply_instance,
  decidable_le    := assume a b, rat.decidable_nonneg (b - a) }

/- Extra instances to short-circuit type class resolution -/
instance : has_lt ℚ          := by apply_instance
instance : distrib_lattice ℚ := by apply_instance
instance : lattice ℚ         := by apply_instance
instance : semilattice_inf ℚ := by apply_instance
instance : semilattice_sup ℚ := by apply_instance
instance : has_inf ℚ         := by apply_instance
instance : has_sup ℚ         := by apply_instance
instance : partial_order ℚ   := by apply_instance
instance : preorder ℚ        := by apply_instance

protected lemma le_def' {p q : ℚ} : p ≤ q ↔ p.num * q.denom ≤ q.num * p.denom :=
begin
  rw [←(@num_denom q), ←(@num_denom p)],
  conv_rhs { simp only [num_denom] },
  exact rat.le_def (by exact_mod_cast p.pos) (by exact_mod_cast q.pos)
end

protected lemma lt_def {p q : ℚ} : p < q ↔ p.num * q.denom < q.num * p.denom :=
begin
  rw [lt_iff_le_and_ne, rat.le_def'],
  suffices : p ≠ q ↔ p.num * q.denom ≠ q.num * p.denom, by
  { split; intro h,
    { exact lt_iff_le_and_ne.elim_right ⟨h.left, (this.elim_left h.right)⟩ },
    { have tmp := lt_iff_le_and_ne.elim_left h, exact ⟨tmp.left, this.elim_right tmp.right⟩ }},
  exact (not_iff_not.elim_right eq_iff_mul_eq_mul)
end

theorem nonneg_iff_zero_le {a} : rat.nonneg a ↔ 0 ≤ a :=
show rat.nonneg a ↔ rat.nonneg (a - 0), by simp

theorem num_nonneg_iff_zero_le : ∀ {a : ℚ}, 0 ≤ a.num ↔ 0 ≤ a
| ⟨n, d, h, c⟩ := @nonneg_iff_zero_le ⟨n, d, h, c⟩

protected theorem add_le_add_left {a b c : ℚ} : c + a ≤ c + b ↔ a ≤ b :=
by unfold has_le.le rat.le; rw add_sub_add_left_eq_sub

protected theorem mul_nonneg {a b : ℚ} (ha : 0 ≤ a) (hb : 0 ≤ b) : 0 ≤ a * b :=
by rw ← nonneg_iff_zero_le at ha hb ⊢; exact rat.nonneg_mul ha hb

instance : linear_ordered_field ℚ :=
{ zero_le_one     := dec_trivial,
  add_le_add_left := assume a b ab c, rat.add_le_add_left.2 ab,
  mul_pos         := assume a b ha hb, lt_of_le_of_ne
    (rat.mul_nonneg (le_of_lt ha) (le_of_lt hb))
    (mul_ne_zero (ne_of_lt ha).symm (ne_of_lt hb).symm).symm,
  ..rat.field,
  ..rat.linear_order,
  ..rat.semiring }

/- Extra instances to short-circuit type class resolution -/
instance : linear_ordered_comm_ring ℚ       := by apply_instance
instance : linear_ordered_ring ℚ            := by apply_instance
instance : ordered_ring ℚ                   := by apply_instance
instance : linear_ordered_semiring ℚ        := by apply_instance
instance : ordered_semiring ℚ               := by apply_instance
instance : linear_ordered_add_comm_group ℚ  := by apply_instance
instance : ordered_add_comm_group ℚ         := by apply_instance
instance : ordered_cancel_add_comm_monoid ℚ := by apply_instance
instance : ordered_add_comm_monoid ℚ        := by apply_instance

attribute [irreducible] rat.le

theorem num_pos_iff_pos {a : ℚ} : 0 < a.num ↔ 0 < a :=
lt_iff_lt_of_le_iff_le $
by simpa [(by cases a; refl : (-a).num = -a.num)]
   using @num_nonneg_iff_zero_le (-a)

lemma div_lt_div_iff_mul_lt_mul {a b c d : ℤ} (b_pos : 0 < b) (d_pos : 0 < d) :
  (a : ℚ) / b < c / d ↔ a * d < c * b :=
begin
  simp only [lt_iff_le_not_le],
  apply and_congr,
  { simp [div_num_denom, (rat.le_def b_pos d_pos)] },
  { apply not_iff_not_of_iff, simp [div_num_denom, (rat.le_def d_pos b_pos)] }
end

lemma lt_one_iff_num_lt_denom {q : ℚ} : q < 1 ↔ q.num < q.denom :=
by simp [rat.lt_def]

theorem abs_def (q : ℚ) : |q| = q.num.nat_abs /. q.denom :=
begin
  cases le_total q 0 with hq hq,
  { rw [abs_of_nonpos hq],
    rw [←(@num_denom q), ← mk_zero_one, rat.le_def (int.coe_nat_pos.2 q.pos) zero_lt_one,
        mul_one, zero_mul] at hq,
    rw [int.of_nat_nat_abs_of_nonpos hq, ← neg_def, num_denom] },
  { rw [abs_of_nonneg hq],
    rw [←(@num_denom q), ← mk_zero_one, rat.le_def zero_lt_one (int.coe_nat_pos.2 q.pos),
        mul_one, zero_mul] at hq,
    rw [int.nat_abs_of_nonneg hq, num_denom] }
end

end rat

-- We make some assertions here about declarations that do not need to be in the import dependencies
-- for this file, but have been in the past.
assert_not_exists fintype
assert_not_exists set.Icc
assert_not_exists galois_connection
-- These are less significant, but should not be relaxed until at least after port to Lean 4.
assert_not_exists linear_ordered_comm_group_with_zero
-- This one doesn't exist anywhere!
-- assert_not_exists positive.add_comm_semigroup


/-
Copyright (c) 2021 Yury G. Kudryashov. All rights reserved.
Released under Apache 2.0 license as described in the file LICENSE.
Authors: Yury G. Kudryashov
-/
import analysis.calculus.cont_diff

/-!
# Smoothness of `real.sqrt`

In this file we prove that `real.sqrt` is infinitely smooth at all points `x ≠ 0` and provide some
dot-notation lemmas.

## Tags

sqrt, differentiable
-/

open set
open_locale topological_space

namespace real

/-- Local homeomorph between `(0, +∞)` and `(0, +∞)` with `to_fun = λ x, x ^ 2` and
`inv_fun = sqrt`. -/
noncomputable def sq_local_homeomorph : local_homeomorph ℝ ℝ :=
{ to_fun := λ x, x ^ 2,
  inv_fun := sqrt,
  source := Ioi 0,
  target := Ioi 0,
  map_source' := λ x hx, mem_Ioi.2 (pow_pos hx _),
  map_target' := λ x hx, mem_Ioi.2 (sqrt_pos.2 hx),
  left_inv' := λ x hx, sqrt_sq (le_of_lt hx),
  right_inv' := λ x hx, sq_sqrt (le_of_lt hx),
  open_source := is_open_Ioi,
  open_target := is_open_Ioi,
  continuous_to_fun := (continuous_pow 2).continuous_on,
  continuous_inv_fun := continuous_on_id.sqrt }

lemma deriv_sqrt_aux {x : ℝ} (hx : x ≠ 0) :
  has_strict_deriv_at sqrt (1 / (2 * sqrt x)) x ∧ ∀ n, cont_diff_at ℝ n sqrt x :=
begin
  cases hx.lt_or_lt with hx hx,
  { rw [sqrt_eq_zero_of_nonpos hx.le, mul_zero, div_zero],
    have : sqrt =ᶠ[𝓝 x] (λ _, 0) := (gt_mem_nhds hx).mono (λ x hx, sqrt_eq_zero_of_nonpos hx.le),
    exact ⟨(has_strict_deriv_at_const x (0 : ℝ)).congr_of_eventually_eq this.symm,
      λ n, cont_diff_at_const.congr_of_eventually_eq this⟩ },
  { have : ↑2 * sqrt x ^ (2 - 1) ≠ 0, by simp [(sqrt_pos.2 hx).ne', @two_ne_zero ℝ],
    split,
    { simpa using sq_local_homeomorph.has_strict_deriv_at_symm hx this
        (has_strict_deriv_at_pow 2 _) },
    { exact λ n, sq_local_homeomorph.cont_diff_at_symm_deriv this hx
        (has_deriv_at_pow 2 (sqrt x)) (cont_diff_at_id.pow 2) } }
end

lemma has_strict_deriv_at_sqrt {x : ℝ} (hx : x ≠ 0) :
  has_strict_deriv_at sqrt (1 / (2 * sqrt x)) x :=
(deriv_sqrt_aux hx).1

lemma cont_diff_at_sqrt {x : ℝ} {n : with_top ℕ} (hx : x ≠ 0) :
  cont_diff_at ℝ n sqrt x :=
(deriv_sqrt_aux hx).2 n

lemma has_deriv_at_sqrt {x : ℝ} (hx : x ≠ 0) : has_deriv_at sqrt (1 / (2 * sqrt x)) x :=
(has_strict_deriv_at_sqrt hx).has_deriv_at

end real

open real

section deriv

variables {f : ℝ → ℝ} {s : set ℝ} {f' x : ℝ}

lemma has_deriv_within_at.sqrt (hf : has_deriv_within_at f f' s x) (hx : f x ≠ 0) :
  has_deriv_within_at (λ y, sqrt (f y)) (f' / (2 * sqrt (f x))) s x :=
by simpa only [(∘), div_eq_inv_mul, mul_one]
  using (has_deriv_at_sqrt hx).comp_has_deriv_within_at x hf

lemma has_deriv_at.sqrt (hf : has_deriv_at f f' x) (hx : f x ≠ 0) :
  has_deriv_at (λ y, sqrt (f y)) (f' / (2 * sqrt(f x))) x :=
by simpa only [(∘), div_eq_inv_mul, mul_one] using (has_deriv_at_sqrt hx).comp x hf

lemma has_strict_deriv_at.sqrt (hf : has_strict_deriv_at f f' x) (hx : f x ≠ 0) :
  has_strict_deriv_at (λ t, sqrt (f t)) (f' / (2 * sqrt (f x))) x :=
by simpa only [(∘), div_eq_inv_mul, mul_one] using (has_strict_deriv_at_sqrt hx).comp x hf

lemma deriv_within_sqrt (hf : differentiable_within_at ℝ f s x) (hx : f x ≠ 0)
  (hxs : unique_diff_within_at ℝ s x) :
  deriv_within (λx, sqrt (f x)) s x = (deriv_within f s x) / (2 * sqrt (f x)) :=
(hf.has_deriv_within_at.sqrt hx).deriv_within hxs

@[simp] lemma deriv_sqrt (hf : differentiable_at ℝ f x) (hx : f x ≠ 0) :
  deriv (λx, sqrt (f x)) x = (deriv f x) / (2 * sqrt (f x)) :=
(hf.has_deriv_at.sqrt hx).deriv

end deriv

section fderiv

variables {E : Type*} [normed_group E] [normed_space ℝ E] {f : E → ℝ} {n : with_top ℕ}
  {s : set E} {x : E} {f' : E →L[ℝ] ℝ}

lemma has_fderiv_at.sqrt (hf : has_fderiv_at f f' x) (hx : f x ≠ 0) :
  has_fderiv_at (λ y, sqrt (f y)) ((1 / (2 * sqrt (f x))) • f') x :=
(has_deriv_at_sqrt hx).comp_has_fderiv_at x hf

lemma has_strict_fderiv_at.sqrt (hf : has_strict_fderiv_at f f' x) (hx : f x ≠ 0) :
  has_strict_fderiv_at (λ y, sqrt (f y)) ((1 / (2 * sqrt (f x))) • f') x :=
(has_strict_deriv_at_sqrt hx).comp_has_strict_fderiv_at x hf

lemma has_fderiv_within_at.sqrt (hf : has_fderiv_within_at f f' s x) (hx : f x ≠ 0) :
  has_fderiv_within_at (λ y, sqrt (f y)) ((1 / (2 * sqrt (f x))) • f') s x :=
(has_deriv_at_sqrt hx).comp_has_fderiv_within_at x hf

lemma differentiable_within_at.sqrt (hf : differentiable_within_at ℝ f s x) (hx : f x ≠ 0) :
  differentiable_within_at ℝ (λ y, sqrt (f y)) s x :=
(hf.has_fderiv_within_at.sqrt hx).differentiable_within_at

lemma differentiable_at.sqrt (hf : differentiable_at ℝ f x) (hx : f x ≠ 0) :
  differentiable_at ℝ (λ y, sqrt (f y)) x :=
(hf.has_fderiv_at.sqrt hx).differentiable_at

lemma differentiable_on.sqrt (hf : differentiable_on ℝ f s) (hs : ∀ x ∈ s, f x ≠ 0) :
  differentiable_on ℝ (λ y, sqrt (f y)) s :=
λ x hx, (hf x hx).sqrt (hs x hx)

lemma differentiable.sqrt (hf : differentiable ℝ f) (hs : ∀ x, f x ≠ 0) :
  differentiable ℝ (λ y, sqrt (f y)) :=
λ x, (hf x).sqrt (hs x)

lemma fderiv_within_sqrt (hf : differentiable_within_at ℝ f s x) (hx : f x ≠ 0)
  (hxs : unique_diff_within_at ℝ s x) :
  fderiv_within ℝ (λx, sqrt (f x)) s x = (1 / (2 * sqrt (f x))) • fderiv_within ℝ f s x :=
(hf.has_fderiv_within_at.sqrt hx).fderiv_within hxs

@[simp] lemma fderiv_sqrt (hf : differentiable_at ℝ f x) (hx : f x ≠ 0) :
  fderiv ℝ (λx, sqrt (f x)) x = (1 / (2 * sqrt (f x))) • fderiv ℝ f x :=
(hf.has_fderiv_at.sqrt hx).fderiv

lemma cont_diff_at.sqrt (hf : cont_diff_at ℝ n f x) (hx : f x ≠ 0) :
  cont_diff_at ℝ n (λ y, sqrt (f y)) x :=
(cont_diff_at_sqrt hx).comp x hf

lemma cont_diff_within_at.sqrt (hf : cont_diff_within_at ℝ n f s x) (hx : f x ≠ 0) :
  cont_diff_within_at ℝ n (λ y, sqrt (f y)) s x :=
(cont_diff_at_sqrt hx).comp_cont_diff_within_at x hf

lemma cont_diff_on.sqrt (hf : cont_diff_on ℝ n f s) (hs : ∀ x ∈ s, f x ≠ 0) :
  cont_diff_on ℝ n (λ y, sqrt (f y)) s :=
λ x hx, (hf x hx).sqrt (hs x hx)

lemma cont_diff.sqrt (hf : cont_diff ℝ n f) (h : ∀ x, f x ≠ 0) :
  cont_diff ℝ n (λ y, sqrt (f y)) :=
cont_diff_iff_cont_diff_at.2 $ λ x, (hf.cont_diff_at.sqrt (h x))

end fderiv


-- based on Jeremy's Lean2 formalization

import algebra.module
import analysis.normed_space.basic
import data.real.basic
import linear_algebra.basic

local attribute [instance] classical.prop_decidable
noncomputable theory

-- TODO: move
lemma le_of_sqr_le_sqr {a : ℝ} {b : ℝ} (ha : 0 ≤ a) (hb : 0 ≤ b) (hab : a ^ 2 ≤ b ^ 2) : a ≤ b :=
begin
  rw [pow_two,pow_two] at hab,
  apply or.elim (le_or_gt a b) (λh, h),
  assume h,
  apply false.elim,
  apply lt_irrefl (b * b),
  exact  (lt_of_lt_of_le (mul_self_lt_mul_self hb h) hab)
end

class has_inner (V : Type*) (W : Type*):=
(inner : W → W → V)

notation `⟪` v `, ` w `⟫` := has_inner.inner ℝ v w

--TODO: try to move add_comm_group in front and use `attribute [-instance] nat.cast_coe`
class real_inner_product_space (V : Type*) extends has_inner ℝ V, add_comm_group V, vector_space ℝ V :=
(inner_add_left : ∀ u v w, inner (u + v) w = inner u w + inner v w)
(inner_smul_left : ∀ r v w, inner (r • v) w = r * inner v w)
(inner_comm : ∀ v w, inner v w = inner w v)
(inner_self_nonneg : ∀ v, 0 ≤ inner v v)
(eq_zero_of_inner_self_eq_zero : ∀ {v}, inner v v = 0 → v = 0)

namespace real_inner_product_space

variables
  {V : Type*} [real_inner_product_space V]
  {W : Type*} [real_inner_product_space W]

open real_inner_product_space

@[simp] lemma inner_add_right (u v w : V) : ⟪u, v + w⟫ = ⟪u, v⟫ + ⟪u, w⟫ :=
by rw [inner_comm, inner_add_left, inner_comm, inner_comm w]

@[simp] lemma inner_smul_right (r : ℝ) (v w : V) : ⟪v, r • w⟫ = r * ⟪v, w⟫ :=
by rw [inner_comm, inner_smul_left, inner_comm]

@[simp] lemma inner_neg_left (u v : V) : ⟪-u, v⟫ = -⟪u, v⟫ :=
by rw [←neg_one_smul _ u, inner_smul_left, ←neg_eq_neg_one_mul]

@[simp] lemma inner_neg_right (u v : V) : ⟪u, -v⟫ = -⟪u, v⟫ :=
by rw [inner_comm, inner_neg_left, inner_comm]

lemma neg_inner_neg (x y : V): ⟪ - x, - y ⟫ = ⟪ x, y ⟫ :=
by rw [inner_neg_left, inner_neg_right, neg_neg]

@[simp] lemma inner_sub_left (u v w : V) : ⟪u - v, w⟫ = ⟪u, w⟫ - ⟪v, w⟫ :=
by rw [sub_eq_add_neg, sub_eq_add_neg, inner_add_left, inner_neg_left]

@[simp] lemma inner_sub_right (u v w : V) : ⟪u, v - w⟫ = ⟪u, v⟫ - ⟪u, w⟫ :=
by rw [sub_eq_add_neg, sub_eq_add_neg, inner_add_right, inner_neg_right]

@[simp] lemma inner_zero_left (v : V) : ⟪0, v⟫ = 0 :=
by rw [←zero_smul _ v, inner_smul_left, zero_mul]

@[simp] lemma inner_zero_right (v : V) : ⟪v, 0⟫ = 0 :=
by rw [inner_comm, inner_zero_left]

@[simp] lemma inner_self_pos {v : V} (h : v ≠ 0) : 0 < ⟪v, v⟫ :=
lt_of_le_of_ne (inner_self_nonneg _) (λ  h_inner_0, h (eq_zero_of_inner_self_eq_zero h_inner_0.symm))

def orthogonal (u v : V) : Prop := ⟪u, v⟫ = 0

infix ` ⊥ `:50 := orthogonal

lemma orthogonal_comm {u v : V} (H : u ⊥ v) : v ⊥ u :=
by unfold orthogonal at *; rw [inner_comm, H]

section

/- first, we define norm internally, to show that an inner product space is a normed space -/

private def ip_norm (v : V):= real.sqrt ⟪v, v⟫

private lemma ip_norm_zero : ip_norm (0 : V) = 0 :=
by rw [ip_norm, inner_zero_left, real.sqrt_zero]

private lemma ip_norm_squared (v : V) : (ip_norm v) ^2 = ⟪v, v⟫ :=
real.sqr_sqrt (inner_self_nonneg v)

private lemma ip_norm_nonneg (v : V) : 0 ≤ ip_norm v := real.sqrt_nonneg _

private lemma eq_zero_of_ip_norm_eq_zero {v : V} (H : ip_norm v = 0) : v = 0 :=
have ⟪v, v⟫ = 0, by rw [←ip_norm_squared, H, pow_two, zero_mul],
eq_zero_of_inner_self_eq_zero this

private lemma ip_norm_eq_zero_iff (v : V) : ip_norm v = 0 ↔ v = 0 :=
begin
  apply iff.intro,
  { intro h,
    apply eq_zero_of_ip_norm_eq_zero h },
  { intro h,
    rw [h, ip_norm_zero] }
end

private lemma ip_norm_neg (v : V) : ip_norm (- v) = ip_norm v :=
by rw [ip_norm, inner_neg_left, inner_neg_right , neg_neg, ip_norm]

private lemma ip_norm_smul (r : ℝ) (v : V) : ip_norm (r • v) = abs r * ip_norm v :=
begin
  rw [ip_norm, inner_smul_left, inner_smul_right , ←mul_assoc],
  rw [real.sqrt_mul (mul_self_nonneg r) _, real.sqrt_mul_self_eq_abs, ip_norm]
end

private lemma ip_norm_pythagorean {u v : V} (ortho : u ⊥ v) :
    (ip_norm (u + v))^2 = (ip_norm u)^2 + (ip_norm v)^2 :=
begin
  rw [orthogonal] at ortho,
  rw [ip_norm_squared, ip_norm_squared, inner_add_right, inner_add_left, inner_add_left],
  rw [inner_comm v u, ortho, zero_add, add_zero, ip_norm, real.sqr_sqrt (inner_self_nonneg _)]
end

private def ip_proj_on (u : V) {v : V} (H : v ≠ 0) : V :=
(⟪u, v⟫ / (ip_norm v)^2) • v

private lemma ip_proj_on_orthogonal (u : V) {v : V} (H : v ≠ 0) :
  ip_proj_on u H ⊥ (u - ip_proj_on u H) :=
begin
  rw [ip_proj_on, orthogonal, inner_sub_right, inner_smul_left, inner_smul_left, inner_smul_right],
  rw [ip_norm_squared],
  rw [div_mul_cancel _ (assume H', H (eq_zero_of_inner_self_eq_zero H'))],
  rw [inner_comm v u, sub_self]
end

private lemma ip_norm_proj_on_eq (u : V) {v : V} (H : v ≠ 0) :
  ip_norm (ip_proj_on u H) = abs ⟪u, v⟫ / ip_norm v :=
have H1 : ip_norm v ≠ 0, from assume H', H (eq_zero_of_ip_norm_eq_zero H'),
begin
  rw [ip_proj_on, ip_norm_smul, abs_div, abs_of_nonneg (pow_two_nonneg (ip_norm v)), pow_two],
  rw [div_mul_eq_mul_div, ←div_mul_div, div_self H1, mul_one]
end

private lemma ip_norm_squared_pythagorean (u : V) {v : V} (H : v ≠ 0) :
  (ip_norm u)^2 = (ip_norm (u - ip_proj_on u H))^2 + (ip_norm (ip_proj_on u H))^2 :=
calc
  (ip_norm u)^2 = (ip_norm (u - ip_proj_on u H + ip_proj_on u H))^2 :
                    by rw sub_add_cancel
            ... = (ip_norm (u - ip_proj_on u H))^2 + (ip_norm (ip_proj_on u H))^2 :
                    ip_norm_pythagorean (orthogonal_comm (ip_proj_on_orthogonal u H))

private lemma ip_norm_proj_on_le (u : V) {v : V} (H : v ≠ 0) :
  ip_norm (ip_proj_on u H) ≤ ip_norm u :=
have (ip_norm u)^2 ≥ (ip_norm (ip_proj_on u H))^2,
  begin
    rw [ip_norm_squared_pythagorean u H],
    apply le_add_of_nonneg_left (pow_two_nonneg (ip_norm (u - ip_proj_on u H)))
  end,
le_of_sqr_le_sqr (ip_norm_nonneg _) (ip_norm_nonneg _) this

private lemma ip_cauchy_schwartz (u v : V) : abs ⟪u, v⟫ ≤ ip_norm u * ip_norm v :=
begin
  by_cases h_cases : v = (0 : V),
  { rw [h_cases, inner_zero_right, abs_zero, ip_norm_zero, mul_zero] },
  { have h_norm_ne : ip_norm v ≠ 0, from λH, h_cases (eq_zero_of_ip_norm_eq_zero H),
    have h_norm_gt : ip_norm v > 0, from lt_of_le_of_ne (real.sqrt_nonneg _) (ne.symm h_norm_ne),
    let H := ip_norm_proj_on_le u h_cases,
    rw [ip_norm_proj_on_eq u h_cases] at H,
    exact (div_le_iff h_norm_gt).1 H
 }
end

private lemma ip_cauchy_schwartz' (u v : V) : ⟪u, v⟫ ≤ ip_norm u * ip_norm v :=
le_trans (le_abs_self _) (ip_cauchy_schwartz _ _)

private lemma ip_norm_triangle (u v : V) : ip_norm (u + v) ≤ ip_norm u + ip_norm v :=
have H : ⟪u, v⟫ ≤ ip_norm u * ip_norm v, from ip_cauchy_schwartz' u v,
have (ip_norm (u + v))^2 ≤ (ip_norm u + ip_norm v)^2, from
  calc
    (ip_norm (u + v))^2 = (ip_norm u)^2 + (ip_norm v)^2 + ⟪u, v⟫ + ⟪u, v⟫ :
            begin simp only [ip_norm, real.sqr_sqrt (inner_self_nonneg _)],
              rw [inner_add_left, inner_add_right, inner_add_right, inner_comm v u],
              rw [←add_assoc, ←add_right_comm _ _ ⟪v, v⟫, ←add_right_comm _ _ ⟪v, v⟫]
            end
    ... ≤ (ip_norm u)^2 + (ip_norm v)^2 + ip_norm u * ip_norm v + ⟪u, v⟫ :
            add_le_add_right (add_le_add_left H _) _
    ... ≤ (ip_norm u)^2 + (ip_norm v)^2 + ip_norm u * ip_norm v + ip_norm u * ip_norm v :
            add_le_add_left H _
    ... = (ip_norm u + ip_norm v)^2 :
            by rw [pow_two, pow_two, pow_two, right_distrib, left_distrib, left_distrib, ←add_assoc,
                         add_right_comm _ (ip_norm v * ip_norm v),
                         add_right_comm _ (ip_norm v * ip_norm v),
                         mul_comm (ip_norm v) (ip_norm u)],
le_of_sqr_le_sqr (ip_norm_nonneg _) (add_nonneg (ip_norm_nonneg _) (ip_norm_nonneg _)) this

instance has_norm [real_inner_product_space V] :
has_norm V := { norm := ip_norm }.

lemma normed_group_core : normed_group.core V :=
{
  norm_eq_zero_iff := ip_norm_eq_zero_iff,
  triangle := ip_norm_triangle,
  norm_neg := ip_norm_neg
}

instance is_normed_group [real_inner_product_space V] :
  normed_group V :=
normed_group.of_core _ normed_group_core

-- TODO: Should we have a similar setup like "normed_group_core" for inner_product_space?

instance is_normed_space [real_inner_product_space V] :
  normed_space ℝ V :=
{
  norm_smul := ip_norm_smul
}

end

/- now we restate the new theorems using the norm notation -/

lemma norm_squared (v : V) : ∥ v ∥^2 = ⟪v, v⟫ := ip_norm_squared v

lemma norm_pythagorean {u v : V} (ortho : u ⊥ v) : ∥ u + v ∥^2 = ∥ u ∥^2 + ∥ v ∥^2 :=
ip_norm_pythagorean ortho

def proj_on (u : V) {v : V} (H : v ≠ 0) : V := (⟪u, v⟫ / ∥ v ∥^2) • v

lemma proj_on_orthogonal (u : V) {v : V} (H : v ≠ 0) :
  proj_on u H ⊥ (u - proj_on u H) :=
ip_proj_on_orthogonal u H

lemma norm_proj_on_eq (u : V) {v : V} (H : v ≠ 0) :
  ∥ proj_on u H ∥ = abs ⟪u, v⟫ / ∥ v ∥ :=
ip_norm_proj_on_eq u H

lemma norm_squared_pythagorean (u : V) {v : V} (H : v ≠ 0) :
  ∥ u ∥^2 = ∥ u - proj_on u H ∥^2 + ∥ proj_on u H ∥^2 :=
ip_norm_squared_pythagorean u H

lemma norm_proj_on_le (u : V) {v : V} (H : v ≠ 0) :
  ∥ proj_on u H ∥ ≤ ∥ u ∥ := ip_norm_proj_on_le u H

theorem cauchy_schwartz (u v : V) : abs ⟪u, v⟫ ≤ ∥ u ∥ * ∥ v ∥ := ip_cauchy_schwartz u v

theorem cauchy_schwartz' (u v : V) : ⟪u, v⟫ ≤ ∥ u ∥ * ∥ v ∥ := ip_cauchy_schwartz' u v

theorem eq_proj_on_cauchy_schwartz {u v : V} (H : v ≠ 0) (H₁ : abs ⟪u, v⟫ = ∥ u ∥ * ∥ v ∥) :
  u = proj_on u H :=
have ∥ v ∥ ≠ 0, from assume H', H ((normed_group_core.norm_eq_zero_iff _).1 H'),
have ∥ u ∥ = ∥ proj_on u H ∥, by rw [norm_proj_on_eq, H₁, mul_div_cancel _ this],
have ∥ u - proj_on u H ∥^2 + ∥ u ∥^2 = 0 + ∥ u ∥^2,
begin
  rw zero_add,
  convert (norm_squared_pythagorean u H).symm
end,
have ∥ u - proj_on u H ∥^2 = 0, from eq_of_add_eq_add_right this,
show u = proj_on u H,
begin
  rw pow_two at this,
  exact eq_of_sub_eq_zero ((normed_group_core.norm_eq_zero_iff _).1 ((or_self _).1 (mul_eq_zero.1 this)))
end

/- Instances of real_inner_product_space -/

instance real :
  real_inner_product_space ℝ :=
{ real_inner_product_space .
  inner := (*),
  inner_add_left := add_mul,
  inner_smul_left := mul_assoc,
  inner_comm := mul_comm,
  inner_self_nonneg := mul_self_nonneg,
  eq_zero_of_inner_self_eq_zero := by apply eq_zero_of_mul_self_eq_zero,
}

-- TODO: move
@[simp] lemma real.ring_add (x y : ℝ) : ring.add x y = x + y := rfl
@[simp] lemma real.no_zero_divisors_mul (x y : ℝ) : no_zero_divisors.mul x y = x * y := rfl

section
set_option class.instance_max_depth 50
instance prod {V : Type*} [real_inner_product_space V] {W : Type*} [real_inner_product_space W]:
  real_inner_product_space (V × W):=
{
  inner := λ x y, ⟪x.1,y.1⟫ + ⟪x.2,y.2⟫,
  inner_add_left :=
  begin
    intros u v w,
    dsimp [inner_add_left],
    let H1 := @inner_add_left V _ u.fst v.fst w.fst,
    let H2 := @inner_add_left W _ u.snd v.snd w.snd,
    unfold add_group.add, unfold add_comm_group.add, unfold add_comm_semigroup.add, unfold add_semigroup.add,
    simp [H1, H2] --TODO: why so complicated?
  end,
  inner_smul_left := begin simp [inner_smul_left, mul_add], end,
  inner_comm := by simp [inner_comm],
  inner_self_nonneg := by intros; exact add_nonneg (inner_self_nonneg _) (inner_self_nonneg _),
  eq_zero_of_inner_self_eq_zero :=
    begin
      intros x hx,
      apply prod.eq_iff_fst_eq_snd_eq.2,
      dsimp at hx,
      rw add_eq_zero_iff_eq_zero_and_eq_zero_of_nonneg_of_nonneg
          (inner_self_nonneg _) (inner_self_nonneg _) at hx,
      apply and.intro,
      { apply eq_zero_of_inner_self_eq_zero hx.1 },
      { apply eq_zero_of_inner_self_eq_zero hx.2 }
    end
}
end

end real_inner_product_space