{-# OPTIONS --cubical-compatible --safe #-}
open import Relation.Binary.Core using (Rel)
open import Relation.Binary.Bundles using (Setoid)
open import Relation.Binary.Structures using (IsEquivalence)
module Function.Structures.Biased {a b ℓ₁ ℓ₂}
  {A : Set a} (_≈₁_ : Rel A ℓ₁) 
  {B : Set b} (_≈₂_ : Rel B ℓ₂) 
  where
open import Data.Product.Base as Product using (∃; _×_; _,_)
open import Function.Base
open import Function.Definitions
open import Function.Structures _≈₁_ _≈₂_
open import Function.Consequences.Setoid
open import Level using (_⊔_)
record IsStrictSurjection (f : A → B) : Set (a ⊔ b ⊔ ℓ₁ ⊔ ℓ₂) where
  field
    isCongruent : IsCongruent f
    strictlySurjective : StrictlySurjective _≈₂_ f
  open IsCongruent isCongruent public
  isSurjection : IsSurjection f
  isSurjection = record
    { isCongruent = isCongruent
    ; surjective = strictlySurjective⇒surjective
        Eq₁.setoid Eq₂.setoid cong strictlySurjective
    }
open IsStrictSurjection public
  using () renaming (isSurjection to isStrictSurjection)
record IsStrictBijection (f : A → B) : Set (a ⊔ b ⊔ ℓ₁ ⊔ ℓ₂) where
  field
    isInjection : IsInjection f
    strictlySurjective  : StrictlySurjective _≈₂_ f
  isBijection : IsBijection f
  isBijection = record
    { isInjection = isInjection
    ; surjective = strictlySurjective⇒surjective
        Eq₁.setoid Eq₂.setoid cong strictlySurjective
    } where open IsInjection isInjection
open IsStrictBijection public
  using () renaming (isBijection to isStrictBijection)
record IsStrictLeftInverse (to : A → B) (from : B → A) : Set (a ⊔ b ⊔ ℓ₁ ⊔ ℓ₂) where
  field
    isCongruent  : IsCongruent to
    from-cong    : Congruent _≈₂_ _≈₁_ from
    strictlyInverseˡ : StrictlyInverseˡ _≈₂_ to from
  isLeftInverse : IsLeftInverse to from
  isLeftInverse = record
    { isCongruent = isCongruent
    ; from-cong = from-cong
    ; inverseˡ = strictlyInverseˡ⇒inverseˡ
        Eq₁.setoid Eq₂.setoid cong strictlyInverseˡ
    } where open IsCongruent isCongruent
open IsStrictLeftInverse public
  using () renaming (isLeftInverse to isStrictLeftInverse)
record IsStrictRightInverse (to : A → B) (from : B → A) : Set (a ⊔ b ⊔ ℓ₁ ⊔ ℓ₂) where
  field
    isCongruent : IsCongruent to
    from-cong   : Congruent _≈₂_ _≈₁_ from
    strictlyInverseʳ : StrictlyInverseʳ _≈₁_ to from
  isRightInverse : IsRightInverse to from
  isRightInverse = record
    { isCongruent = isCongruent
    ; from-cong = from-cong
    ; inverseʳ = strictlyInverseʳ⇒inverseʳ
        Eq₁.setoid Eq₂.setoid from-cong strictlyInverseʳ
    } where open IsCongruent isCongruent
open IsStrictRightInverse public
  using () renaming (isRightInverse to isStrictRightInverse)
record IsStrictInverse (to : A → B) (from : B → A) : Set (a ⊔ b ⊔ ℓ₁ ⊔ ℓ₂) where
  field
    isLeftInverse : IsLeftInverse to from
    strictlyInverseʳ : StrictlyInverseʳ _≈₁_ to from
  isInverse : IsInverse to from
  isInverse = record
    { isLeftInverse = isLeftInverse
    ; inverseʳ      = strictlyInverseʳ⇒inverseʳ
        Eq₁.setoid Eq₂.setoid from-cong strictlyInverseʳ
    } where open IsLeftInverse isLeftInverse
open IsStrictInverse public
  using () renaming (isInverse to isStrictInverse)