{-# OPTIONS --safe --cubical #-}
module Relation.Binary where
open import Level
open import Relation.Nullary
open import Path as ≡ hiding (sym; refl)
open import Data.Sum
open import Function
open import Data.Bool as Bool using (Bool; true; false; T; bool)
open import Relation.Nullary.Decidable
open import Relation.Nullary.Discrete
module _ (_~_ : A → A → Type b) where
  Reflexive : Type _
  Reflexive = ∀ {x} → x ~ x
  Transitive : Type _
  Transitive = ∀ {x y z} → x ~ y → y ~ z → x ~ z
  Symmetric : Type _
  Symmetric = ∀ {x y} → x ~ y → y ~ x
  Decidable : Type _
  Decidable = ∀ x y → Dec (x ~ y)
  Antisymmetric : Type _
  Antisymmetric = ∀ {x y} → x ~ y → y ~ x → x ≡ y
  Total : Type _
  Total = ∀ x y → (x ~ y) ⊎ (y ~ x)
data Tri {a r₁ r₂ r₃} {A : Type a} (R₁ : A → A → Type r₁) (R₂ : A → A → Type r₂) (R₃ : A → A → Type r₃) (x y : A) : Type (a ℓ⊔ r₁ ℓ⊔ r₂ ℓ⊔ r₃) where
  lt : (x<y : R₁ x y) → Tri R₁ R₂ R₃ x y
  eq : (x≡y : R₂ x y) → Tri R₁ R₂ R₃ x y
  gt : (x>y : R₃ x y) → Tri R₁ R₂ R₃ x y
record PartialOrder {ℓ₁} (𝑆 : Type ℓ₁) ℓ₂ : Type (ℓ₁ ℓ⊔ ℓsuc ℓ₂) where
  infix 4 _≤_
  field
    _≤_ : 𝑆 → 𝑆 → Type ℓ₂
    refl : Reflexive _≤_
    antisym : Antisymmetric _≤_
    trans : Transitive _≤_
record TotalOrder {ℓ₁} (𝑆 : Type ℓ₁) ℓ₂ : Type (ℓ₁ ℓ⊔ ℓsuc ℓ₂) where
  field
    partialOrder : PartialOrder 𝑆 ℓ₂
  open PartialOrder partialOrder public
  infix 4 _≤ᵇ_ _≤?_
  field
    _≤?_ : Total _≤_
  _≤ᵇ_ : 𝑆 → 𝑆 → Bool
  x ≤ᵇ y = is-l (x ≤? y)
  open import Data.Unit
  open import Data.Empty
  open import Data.Sigma
  total⇒discrete : Discrete 𝑆
  total⇒discrete x y with x ≤? y | inspect (x ≤?_) y | y ≤? x | inspect (y ≤?_) x
  total⇒discrete x y | inl x₁ | 〖 xy 〗 | inl x₂ | 〖 yx 〗 = yes (antisym x₁ x₂)
  total⇒discrete x y | inr x₁ | 〖 xy 〗 | inr x₂ | 〖 yx 〗 = yes (antisym x₂ x₁)
  total⇒discrete x y | inl x₁ | 〖 xy 〗 | inr x₂ | 〖 yx 〗 = no (λ p → subst (bool ⊥ ⊤) (cong is-l (≡.sym xy) ; cong₂ _≤ᵇ_ p (≡.sym p) ; cong is-l yx) tt)
  total⇒discrete x y | inr x₁ | 〖 xy 〗 | inl x₂ | 〖 yx 〗 = no (λ p → subst (bool ⊤ ⊥) (cong is-l (≡.sym xy) ; cong₂ _≤ᵇ_ p (≡.sym p) ; cong is-l yx) tt)
  infix 4 _<_
  _<_ : 𝑆 → 𝑆 → Type (ℓ₁ ℓ⊔ ℓ₂)
  x < y = (x ≢ y) × (x ≤ y)
  Ordering : 𝑆 → 𝑆 → Type (ℓ₁ ℓ⊔ ℓ₂)
  Ordering = Tri _<_ _≡_ (flip _<_)
  compare : ∀ x y → Ordering x y
  compare x y with x ≤? y | inspect (x ≤?_) y | y ≤? x | inspect (y ≤?_) x
  compare x y | inl x₁ | 〖 xy 〗 | inl x₂ | 〖 yx 〗 = eq (antisym x₁ x₂)
  compare x y | inr x₁ | 〖 xy 〗 | inr x₂ | 〖 yx 〗 = eq (antisym x₂ x₁)
  compare x y | inl x₁ | 〖 xy 〗 | inr x₂ | 〖 yx 〗 = lt ((λ p → subst (bool ⊥ ⊤) (cong is-l (≡.sym xy) ; cong₂ _≤ᵇ_ p (≡.sym p) ; cong is-l yx) tt) , x₁)
  compare x y | inr x₁ | 〖 xy 〗 | inl x₂ | 〖 yx 〗 = gt ((λ p → subst (bool ⊤ ⊥) (cong is-l (≡.sym xy) ; cong₂ _≤ᵇ_ (≡.sym p) p ; cong is-l yx) tt) , x₁)
record Equivalence {ℓ₁} (𝑆 : Type ℓ₁) ℓ₂ : Type (ℓ₁ ℓ⊔ ℓsuc ℓ₂) where
  infix 4 _≋_
  field
    _≋_ : 𝑆 → 𝑆 → Type ℓ₂
    sym   : ∀ {x y} → x ≋ y → y ≋ x
    refl  : ∀ {x} → x ≋ x
    trans : ∀ {x y z} → x ≋ y → y ≋ z → x ≋ z
≡-equivalence : ∀ {a} {A : Set a} → Equivalence A a
≡-equivalence = record
  { _≋_ = _≡_
  ; sym = ≡.sym
  ; refl = ≡.refl
  ; trans = _;_
  }