module Function.Related where
open import Level
open import Function
open import Function.Equality using (_⟨$⟩_)
open import Function.Equivalence as Eq using (Equivalence)
open import Function.Injection as Inj using (Injection; _↣_)
open import Function.Inverse as Inv using (Inverse; _↔_)
open import Function.LeftInverse as LeftInv using (LeftInverse)
open import Function.Surjection as Surj using (Surjection)
open import Relation.Binary
open import Relation.Binary.PropositionalEquality as P using (_≡_)
record _←_ {a b} (A : Set a) (B : Set b) : Set (a ⊔ b) where
constructor lam
field app-← : B → A
open _←_ public
record _↢_ {a b} (A : Set a) (B : Set b) : Set (a ⊔ b) where
constructor lam
field app-↢ : B ↣ A
open _↢_ public
data Kind : Set where
implication : Kind
reverse-implication : Kind
equivalence : Kind
injection : Kind
reverse-injection : Kind
left-inverse : Kind
surjection : Kind
bijection : Kind
infix 4 _∼[_]_
_∼[_]_ : ∀ {ℓ₁ ℓ₂} → Set ℓ₁ → Kind → Set ℓ₂ → Set _
A ∼[ implication ] B = A → B
A ∼[ reverse-implication ] B = A ← B
A ∼[ equivalence ] B = Equivalence (P.setoid A) (P.setoid B)
A ∼[ injection ] B = Injection (P.setoid A) (P.setoid B)
A ∼[ reverse-injection ] B = A ↢ B
A ∼[ left-inverse ] B = LeftInverse (P.setoid A) (P.setoid B)
A ∼[ surjection ] B = Surjection (P.setoid A) (P.setoid B)
A ∼[ bijection ] B = Inverse (P.setoid A) (P.setoid B)
Related : Kind → ∀ {ℓ₁ ℓ₂} → Set ℓ₁ → Set ℓ₂ → Set _
Related k A B = A ∼[ k ] B
↔⇒ : ∀ {k x y} {X : Set x} {Y : Set y} →
X ∼[ bijection ] Y → X ∼[ k ] Y
↔⇒ {implication} = _⟨$⟩_ ∘ Inverse.to
↔⇒ {reverse-implication} = lam ∘′ _⟨$⟩_ ∘ Inverse.from
↔⇒ {equivalence} = Inverse.equivalence
↔⇒ {injection} = Inverse.injection
↔⇒ {reverse-injection} = lam ∘′ Inverse.injection ∘ Inv.sym
↔⇒ {left-inverse} = Inverse.left-inverse
↔⇒ {surjection} = Inverse.surjection
↔⇒ {bijection} = id
≡⇒ : ∀ {k ℓ} {X Y : Set ℓ} → X ≡ Y → X ∼[ k ] Y
≡⇒ P.refl = ↔⇒ Inv.id
data Symmetric-kind : Set where
equivalence : Symmetric-kind
bijection : Symmetric-kind
⌊_⌋ : Symmetric-kind → Kind
⌊ equivalence ⌋ = equivalence
⌊ bijection ⌋ = bijection
data Forward-kind : Set where
implication : Forward-kind
equivalence : Forward-kind
injection : Forward-kind
left-inverse : Forward-kind
surjection : Forward-kind
bijection : Forward-kind
⌊_⌋→ : Forward-kind → Kind
⌊ implication ⌋→ = implication
⌊ equivalence ⌋→ = equivalence
⌊ injection ⌋→ = injection
⌊ left-inverse ⌋→ = left-inverse
⌊ surjection ⌋→ = surjection
⌊ bijection ⌋→ = bijection
⇒→ : ∀ {k x y} {X : Set x} {Y : Set y} → X ∼[ ⌊ k ⌋→ ] Y → X → Y
⇒→ {implication} = id
⇒→ {equivalence} = _⟨$⟩_ ∘ Equivalence.to
⇒→ {injection} = _⟨$⟩_ ∘ Injection.to
⇒→ {left-inverse} = _⟨$⟩_ ∘ LeftInverse.to
⇒→ {surjection} = _⟨$⟩_ ∘ Surjection.to
⇒→ {bijection} = _⟨$⟩_ ∘ Inverse.to
data Backward-kind : Set where
reverse-implication : Backward-kind
equivalence : Backward-kind
reverse-injection : Backward-kind
left-inverse : Backward-kind
surjection : Backward-kind
bijection : Backward-kind
⌊_⌋← : Backward-kind → Kind
⌊ reverse-implication ⌋← = reverse-implication
⌊ equivalence ⌋← = equivalence
⌊ reverse-injection ⌋← = reverse-injection
⌊ left-inverse ⌋← = left-inverse
⌊ surjection ⌋← = surjection
⌊ bijection ⌋← = bijection
⇒← : ∀ {k x y} {X : Set x} {Y : Set y} → X ∼[ ⌊ k ⌋← ] Y → Y → X
⇒← {reverse-implication} = app-←
⇒← {equivalence} = _⟨$⟩_ ∘ Equivalence.from
⇒← {reverse-injection} = _⟨$⟩_ ∘ Injection.to ∘ app-↢
⇒← {left-inverse} = _⟨$⟩_ ∘ LeftInverse.from
⇒← {surjection} = _⟨$⟩_ ∘ Surjection.from
⇒← {bijection} = _⟨$⟩_ ∘ Inverse.from
data Equivalence-kind : Set where
equivalence : Equivalence-kind
left-inverse : Equivalence-kind
surjection : Equivalence-kind
bijection : Equivalence-kind
⌊_⌋⇔ : Equivalence-kind → Kind
⌊ equivalence ⌋⇔ = equivalence
⌊ left-inverse ⌋⇔ = left-inverse
⌊ surjection ⌋⇔ = surjection
⌊ bijection ⌋⇔ = bijection
⇒⇔ : ∀ {k x y} {X : Set x} {Y : Set y} →
X ∼[ ⌊ k ⌋⇔ ] Y → X ∼[ equivalence ] Y
⇒⇔ {equivalence} = id
⇒⇔ {left-inverse} = LeftInverse.equivalence
⇒⇔ {surjection} = Surjection.equivalence
⇒⇔ {bijection} = Inverse.equivalence
⇔⌊_⌋ : Symmetric-kind → Equivalence-kind
⇔⌊ equivalence ⌋ = equivalence
⇔⌊ bijection ⌋ = bijection
→⌊_⌋ : Equivalence-kind → Forward-kind
→⌊ equivalence ⌋ = equivalence
→⌊ left-inverse ⌋ = left-inverse
→⌊ surjection ⌋ = surjection
→⌊ bijection ⌋ = bijection
←⌊_⌋ : Equivalence-kind → Backward-kind
←⌊ equivalence ⌋ = equivalence
←⌊ left-inverse ⌋ = left-inverse
←⌊ surjection ⌋ = surjection
←⌊ bijection ⌋ = bijection
_op : Kind → Kind
implication op = reverse-implication
reverse-implication op = implication
equivalence op = equivalence
injection op = reverse-injection
reverse-injection op = injection
left-inverse op = surjection
surjection op = left-inverse
bijection op = bijection
reverse : ∀ {k a b} {A : Set a} {B : Set b} →
A ∼[ k ] B → B ∼[ k op ] A
reverse {implication} = lam
reverse {reverse-implication} = app-←
reverse {equivalence} = Eq.sym
reverse {injection} = lam
reverse {reverse-injection} = app-↢
reverse {left-inverse} = Surj.fromRightInverse
reverse {surjection} = Surjection.right-inverse
reverse {bijection} = Inv.sym
module EquationalReasoning where
private
refl : ∀ {k ℓ} → Reflexive (Related k {ℓ})
refl {implication} = id
refl {reverse-implication} = lam id
refl {equivalence} = Eq.id
refl {injection} = Inj.id
refl {reverse-injection} = lam Inj.id
refl {left-inverse} = LeftInv.id
refl {surjection} = Surj.id
refl {bijection} = Inv.id
trans : ∀ {k ℓ₁ ℓ₂ ℓ₃} →
Trans (Related k {ℓ₁} {ℓ₂})
(Related k {ℓ₂} {ℓ₃})
(Related k {ℓ₁} {ℓ₃})
trans {implication} = flip _∘′_
trans {reverse-implication} = λ f g → lam (app-← f ∘ app-← g)
trans {equivalence} = flip Eq._∘_
trans {injection} = flip Inj._∘_
trans {reverse-injection} = λ f g → lam (Inj._∘_ (app-↢ f) (app-↢ g))
trans {left-inverse} = flip LeftInv._∘_
trans {surjection} = flip Surj._∘_
trans {bijection} = flip Inv._∘_
sym : ∀ {k ℓ₁ ℓ₂} →
Sym (Related ⌊ k ⌋ {ℓ₁} {ℓ₂})
(Related ⌊ k ⌋ {ℓ₂} {ℓ₁})
sym {equivalence} = Eq.sym
sym {bijection} = Inv.sym
infix 3 _∎
infixr 2 _∼⟨_⟩_ _↔⟨_⟩_ _↔⟨⟩_ _≡⟨_⟩_
_∼⟨_⟩_ : ∀ {k x y z} (X : Set x) {Y : Set y} {Z : Set z} →
X ∼[ k ] Y → Y ∼[ k ] Z → X ∼[ k ] Z
_ ∼⟨ X↝Y ⟩ Y↝Z = trans X↝Y Y↝Z
_↔⟨_⟩_ : ∀ {k x y z} (X : Set x) {Y : Set y} {Z : Set z} →
X ↔ Y → Y ∼[ k ] Z → X ∼[ k ] Z
X ↔⟨ X↔Y ⟩ Y⇔Z = X ∼⟨ ↔⇒ X↔Y ⟩ Y⇔Z
_↔⟨⟩_ : ∀ {k x y} (X : Set x) {Y : Set y} →
X ∼[ k ] Y → X ∼[ k ] Y
X ↔⟨⟩ X⇔Y = X⇔Y
_≡⟨_⟩_ : ∀ {k ℓ z} (X : Set ℓ) {Y : Set ℓ} {Z : Set z} →
X ≡ Y → Y ∼[ k ] Z → X ∼[ k ] Z
X ≡⟨ X≡Y ⟩ Y⇔Z = X ∼⟨ ≡⇒ X≡Y ⟩ Y⇔Z
_∎ : ∀ {k x} (X : Set x) → X ∼[ k ] X
X ∎ = refl
setoid : Symmetric-kind → (ℓ : Level) → Setoid _ _
setoid k ℓ = record
{ Carrier = Set ℓ
; _≈_ = Related ⌊ k ⌋
; isEquivalence =
record {refl = _ ∎; sym = sym; trans = _∼⟨_⟩_ _}
} where open EquationalReasoning
preorder : Kind → (ℓ : Level) → Preorder _ _ _
preorder k ℓ = record
{ Carrier = Set ℓ
; _≈_ = _↔_
; _∼_ = Related k
; isPreorder = record
{ isEquivalence = Setoid.isEquivalence (setoid bijection ℓ)
; reflexive = ↔⇒
; trans = _∼⟨_⟩_ _
}
} where open EquationalReasoning
InducedRelation₁ : Kind → ∀ {a s} {A : Set a} →
(A → Set s) → A → A → Set _
InducedRelation₁ k S = λ x y → S x ∼[ k ] S y
InducedPreorder₁ : Kind → ∀ {a s} {A : Set a} →
(A → Set s) → Preorder _ _ _
InducedPreorder₁ k S = record
{ _≈_ = P._≡_
; _∼_ = InducedRelation₁ k S
; isPreorder = record
{ isEquivalence = P.isEquivalence
; reflexive = reflexive ∘
Setoid.reflexive (setoid bijection _) ∘
P.cong S
; trans = trans
}
} where open Preorder (preorder _ _)
InducedEquivalence₁ : Symmetric-kind → ∀ {a s} {A : Set a} →
(A → Set s) → Setoid _ _
InducedEquivalence₁ k S = record
{ _≈_ = InducedRelation₁ ⌊ k ⌋ S
; isEquivalence = record {refl = refl; sym = sym; trans = trans}
} where open Setoid (setoid _ _)
InducedRelation₂ : Kind → ∀ {a b s} {A : Set a} {B : Set b} →
(A → B → Set s) → B → B → Set _
InducedRelation₂ k _S_ = λ x y → ∀ {z} → (z S x) ∼[ k ] (z S y)
InducedPreorder₂ : Kind → ∀ {a b s} {A : Set a} {B : Set b} →
(A → B → Set s) → Preorder _ _ _
InducedPreorder₂ k _S_ = record
{ _≈_ = P._≡_
; _∼_ = InducedRelation₂ k _S_
; isPreorder = record
{ isEquivalence = P.isEquivalence
; reflexive = λ x≡y {z} →
reflexive $
Setoid.reflexive (setoid bijection _) $
P.cong (_S_ z) x≡y
; trans = λ i↝j j↝k → trans i↝j j↝k
}
} where open Preorder (preorder _ _)
InducedEquivalence₂ : Symmetric-kind →
∀ {a b s} {A : Set a} {B : Set b} →
(A → B → Set s) → Setoid _ _
InducedEquivalence₂ k _S_ = record
{ _≈_ = InducedRelation₂ ⌊ k ⌋ _S_
; isEquivalence = record
{ refl = refl
; sym = λ i↝j → sym i↝j
; trans = λ i↝j j↝k → trans i↝j j↝k
}
} where open Setoid (setoid _ _)