------------------------------------------------------------------------ -- The Agda standard library -- -- The basic code for equational reasoning with three relations: -- equality, strict ordering and non-strict ordering. ------------------------------------------------------------------------ -- -- See `Data.Nat.Properties` or `Relation.Binary.Reasoning.PartialOrder` -- for examples of how to instantiate this module. {-# OPTIONS --cubical-compatible --safe #-} open import Data.Product.Base using (proj₁; proj₂) open import Level using (_⊔_) open import Function.Base using (case_of_) open import Relation.Nullary.Decidable.Core using (Dec; yes; no) open import Relation.Binary.Core using (Rel; _⇒_) open import Relation.Binary.Structures using (IsPreorder) open import Relation.Binary.Definitions using (Transitive; _Respects₂_; Reflexive; Trans; Irreflexive; Asymmetric) open import Relation.Binary.PropositionalEquality.Core as ≡ using (_≡_) open import Relation.Binary.Reasoning.Syntax module Relation.Binary.Reasoning.Base.Triple {a ℓ₁ ℓ₂ ℓ₃} {A : Set a} {_≈_ : Rel A ℓ₁} {_≤_ : Rel A ℓ₂} {_<_ : Rel A ℓ₃} (isPreorder : IsPreorder _≈_ _≤_) (<-asym : Asymmetric _<_) (<-trans : Transitive _<_) (<-resp-≈ : _<_ Respects₂ _≈_) (<⇒≤ : _<_ ⇒ _≤_) (<-≤-trans : Trans _<_ _≤_ _<_) (≤-<-trans : Trans _≤_ _<_ _<_) where open IsPreorder isPreorder ------------------------------------------------------------------------ -- A datatype to abstract over the current relation infix 4 _IsRelatedTo_ data _IsRelatedTo_ (x y : A) : Set (a ⊔ ℓ₁ ⊔ ℓ₂ ⊔ ℓ₃) where strict : (x<y : x < y) → x IsRelatedTo y nonstrict : (x≤y : x ≤ y) → x IsRelatedTo y equals : (x≈y : x ≈ y) → x IsRelatedTo y start : _IsRelatedTo_ ⇒ _≤_ start (equals x≈y) = reflexive x≈y start (nonstrict x≤y) = x≤y start (strict x<y) = <⇒≤ x<y ≡-go : Trans _≡_ _IsRelatedTo_ _IsRelatedTo_ ≡-go x≡y (equals y≈z) = equals (case x≡y of λ where ≡.refl → y≈z) ≡-go x≡y (nonstrict y≤z) = nonstrict (case x≡y of λ where ≡.refl → y≤z) ≡-go x≡y (strict y<z) = strict (case x≡y of λ where ≡.refl → y<z) ≈-go : Trans _≈_ _IsRelatedTo_ _IsRelatedTo_ ≈-go x≈y (equals y≈z) = equals (Eq.trans x≈y y≈z) ≈-go x≈y (nonstrict y≤z) = nonstrict (∼-respˡ-≈ (Eq.sym x≈y) y≤z) ≈-go x≈y (strict y<z) = strict (proj₂ <-resp-≈ (Eq.sym x≈y) y<z) ≤-go : Trans _≤_ _IsRelatedTo_ _IsRelatedTo_ ≤-go x≤y (equals y≈z) = nonstrict (∼-respʳ-≈ y≈z x≤y) ≤-go x≤y (nonstrict y≤z) = nonstrict (trans x≤y y≤z) ≤-go x≤y (strict y<z) = strict (≤-<-trans x≤y y<z) <-go : Trans _<_ _IsRelatedTo_ _IsRelatedTo_ <-go x<y (equals y≈z) = strict (proj₁ <-resp-≈ y≈z x<y) <-go x<y (nonstrict y≤z) = strict (<-≤-trans x<y y≤z) <-go x<y (strict y<z) = strict (<-trans x<y y<z) stop : Reflexive _IsRelatedTo_ stop = equals Eq.refl ------------------------------------------------------------------------ -- Types that are used to ensure that the final relation proved by the -- chain of reasoning can be converted into the required relation. data IsStrict {x y} : x IsRelatedTo y → Set (a ⊔ ℓ₁ ⊔ ℓ₂ ⊔ ℓ₃) where isStrict : ∀ x<y → IsStrict (strict x<y) IsStrict? : ∀ {x y} (x≲y : x IsRelatedTo y) → Dec (IsStrict x≲y) IsStrict? (strict x<y) = yes (isStrict x<y) IsStrict? (nonstrict _) = no λ() IsStrict? (equals _) = no λ() extractStrict : ∀ {x y} {x≲y : x IsRelatedTo y} → IsStrict x≲y → x < y extractStrict (isStrict x<y) = x<y strictRelation : SubRelation _IsRelatedTo_ _ _ strictRelation = record { IsS = IsStrict ; IsS? = IsStrict? ; extract = extractStrict } ------------------------------------------------------------------------ -- Equality sub-relation data IsEquality {x y} : x IsRelatedTo y → Set (a ⊔ ℓ₁ ⊔ ℓ₂ ⊔ ℓ₃) where isEquality : ∀ x≈y → IsEquality (equals x≈y) IsEquality? : ∀ {x y} (x≲y : x IsRelatedTo y) → Dec (IsEquality x≲y) IsEquality? (strict _) = no λ() IsEquality? (nonstrict _) = no λ() IsEquality? (equals x≈y) = yes (isEquality x≈y) extractEquality : ∀ {x y} {x≲y : x IsRelatedTo y} → IsEquality x≲y → x ≈ y extractEquality (isEquality x≈y) = x≈y eqRelation : SubRelation _IsRelatedTo_ _ _ eqRelation = record { IsS = IsEquality ; IsS? = IsEquality? ; extract = extractEquality } ------------------------------------------------------------------------ -- Reasoning combinators open begin-syntax _IsRelatedTo_ start public open begin-equality-syntax _IsRelatedTo_ eqRelation public open begin-strict-syntax _IsRelatedTo_ strictRelation public open begin-contradiction-syntax _IsRelatedTo_ strictRelation <-asym public open ≡-syntax _IsRelatedTo_ ≡-go public open ≈-syntax _IsRelatedTo_ _IsRelatedTo_ ≈-go Eq.sym public open ≤-syntax _IsRelatedTo_ _IsRelatedTo_ ≤-go public open <-syntax _IsRelatedTo_ _IsRelatedTo_ <-go public open end-syntax _IsRelatedTo_ stop public