packages feed

agda2hs-1.3: lib/Haskell/Law/Ord/Def.agda

module Haskell.Law.Ord.Def where

open import Haskell.Prim
open import Haskell.Prim.Ord
open import Haskell.Prim.Bool
open import Haskell.Prim.Int
open import Haskell.Prim.Word
open import Haskell.Prim.Integer
open import Haskell.Prim.Double
open import Haskell.Prim.Tuple
open import Haskell.Prim.Monoid
open import Haskell.Prim.List
open import Haskell.Prim.Maybe
open import Haskell.Prim.Either

open import Haskell.Prim.Eq
open import Haskell.Law.Eq

open import Haskell.Law.Bool
open import Haskell.Law.Equality

record IsLawfulOrd (a : Set) ⦃ iOrd : Ord a ⦄ : Set₁ where
  field
    overlap ⦃ super ⦄ : IsLawfulEq a

    -- Comparability: x <= y || y <= x = True
    comparability : ∀ (x y : a) → (x <= y || y <= x) ≡ True

    -- Transitivity: if x <= y && y <= z = True, then x <= z = True
    transitivity :  ∀ ( x y z : a ) → ((x <= y) && (y <= z)) ≡ True → (x <= z) ≡ True

    -- Reflexivity: x <= x = True
    reflexivity : ∀ (x : a) → (x <= x) ≡ True

    -- Antisymmetry: if x <= y && y <= x = True, then x == y = True
    antisymmetry : ∀ (x y : a) → ((x <= y) && (y <= x)) ≡ True → (x == y) ≡ True

    -- x >= y = y <= x
    lte2gte : ∀ (x y : a) → (x <= y) ≡ (y >= x)

    -- x < y = x <= y && x /= y
    lt2LteNeq : ∀ (x y : a) → (x < y) ≡ (x <= y && x /= y)

    -- x > y = y < x
    lt2gt : ∀ (x y : a) → (x < y) ≡ (y > x)

    -- x < y = compare x y == LT
    compareLt : ∀ (x y : a) → (x < y) ≡ (compare x y == LT)

    -- x > y = compare x y == GT
    compareGt : ∀ (x y : a) → (x > y) ≡ (compare x y == GT)

    -- x == y = compare x y == EQ
    compareEq : ∀ (x y : a) → (x == y) ≡ (compare x y == EQ)

    -- min x y == if x <= y then x else y = True
    min2if : ∀ (x y : a) → ((min x y) == (if (x <= y) then x else y)) ≡ True

    -- max x y == if x >= y then x else y = True
    max2if : ∀ (x y : a) → ((max x y) == (if (x >= y) then x else y)) ≡ True

open IsLawfulOrd ⦃ ... ⦄ public

--------------------------------------------------
-- Some more helper laws

eq2nlt : ⦃ iOrdA : Ord a ⦄ → ⦃ IsLawfulOrd a ⦄
  → ∀ (x y : a) → (x == y) ≡ True → (x < y) ≡ False
eq2nlt x y h
  rewrite compareEq x y
    | compareLt x y
    | equality (compare x y) EQ h
  = refl

eq2ngt : ⦃ iOrdA : Ord a ⦄ → ⦃ IsLawfulOrd a ⦄
  → ∀ (x y : a) → (x == y) ≡ True → (x > y) ≡ False
eq2ngt x y h
  rewrite compareEq x y
    | compareGt x y
    | equality (compare x y) EQ h
  = refl

lte2LtEq : ⦃ iOrdA : Ord a ⦄ → ⦃ IsLawfulOrd a ⦄
  → ∀ (x y : a) → (x <= y) ≡ (x < y || x == y)
lte2LtEq x y 
  rewrite lt2LteNeq x y
    | compareEq x y
  with (x <= y) in h₁ | (compare x y) in h₂
... | False | LT = refl
... | False | EQ = magic $ exFalso (reflexivity x) $ begin 
    (x <= x)  ≡⟨ (cong (x <=_) (equality x y (begin 
      (x == y)            ≡⟨ compareEq x y ⟩ 
      (compare x y == EQ) ≡⟨ equality' (compare x y) EQ h₂ ⟩ 
      True                ∎ ) ) ) ⟩
    (x <= y)  ≡⟨ h₁ ⟩ 
    False ∎
... | False | GT = refl
... | True  | LT = refl
... | True  | EQ = refl
... | True  | GT = refl

gte2GtEq : ⦃ iOrdA : Ord a ⦄ → ⦃ IsLawfulOrd a ⦄
  → ∀ (x y : a) → (x >= y) ≡ (x > y || x == y)
gte2GtEq x y
  rewrite sym $ lte2gte y x
    | lte2LtEq y x
    | eqSymmetry y x
    | lt2gt y x
  = refl

gte2nlt : ⦃ iOrdA : Ord a ⦄ → ⦃ IsLawfulOrd a ⦄
  → ∀ (x y : a) → (x >= y) ≡ not (x < y)
gte2nlt x y
  rewrite gte2GtEq x y
    | compareGt x y
    | compareEq x y
    | compareLt x y
  with compare x y
... | GT = refl 
... | EQ = refl 
... | LT = refl 

gte2nLT : ⦃ iOrdA : Ord a ⦄ → ⦃ IsLawfulOrd a ⦄
  → ∀ (x y : a) → (x >= y) ≡ (compare x y /= LT)
gte2nLT x y
  rewrite gte2nlt x y
    | compareLt x y
  = refl

lte2ngt : ⦃ iOrdA : Ord a ⦄ → ⦃ IsLawfulOrd a ⦄
  → ∀ (x y : a) → (x <= y) ≡ not (x > y)
lte2ngt x y
  rewrite lte2LtEq x y
    | compareLt x y
    | compareEq x y
    | compareGt x y
  with compare x y
... | GT = refl 
... | EQ = refl 
... | LT = refl 

lte2nGT : ⦃ iOrdA : Ord a ⦄ → ⦃ IsLawfulOrd a ⦄
  → ∀ (x y : a) → (x <= y) ≡ (compare x y /= GT)
lte2nGT x y
  rewrite lte2ngt x y
    | compareGt x y
  = refl

eq2lte : ⦃ iOrdA : Ord a ⦄ → ⦃ IsLawfulOrd a ⦄
  → ∀ (x y : a) → (x == y) ≡ True → (x <= y) ≡ True
eq2lte x y h
  rewrite lte2ngt x y
    | eq2ngt x y h
  = refl

lt2lte : ⦃ iOrdA : Ord a ⦄ → ⦃ IsLawfulOrd a ⦄
  → ∀ (x y : a) → (x < y) ≡ True → (x <= y) ≡ True
lt2lte x y h = &&-rightTrue' (x < y) (x <= y) (x /= y) (lt2LteNeq x y) h

eq2gte : ⦃ iOrdA : Ord a ⦄ → ⦃ IsLawfulOrd a ⦄
  → ∀ (x y : a) → (x == y) ≡ True → (x >= y) ≡ True
eq2gte x y h
  rewrite gte2nlt x y
    | eq2nlt x y h
  = refl

gt2gte : ⦃ iOrdA : Ord a ⦄ → ⦃ IsLawfulOrd a ⦄
  → ∀ (x y : a) → (x > y) ≡ True → (x >= y) ≡ True
gt2gte x y h
  rewrite sym (lt2gt y x)
    | sym (lt2lte y x h)
    | lte2gte y x
  = refl

--------------------------------------------------
-- Postulated instances

postulate instance
  iLawfulOrdNat : IsLawfulOrd Nat

  iLawfulOrdInteger : IsLawfulOrd Integer

  iLawfulOrdInt : IsLawfulOrd Int

  iLawfulOrdWord : IsLawfulOrd Word

  iLawfulOrdDouble : IsLawfulOrd Double

  iLawfulOrdChar : IsLawfulOrd Char

  iLawfulOrdUnit : IsLawfulOrd ⊤

  iLawfulOrdTuple₂ : ⦃ iOrdA : Ord a ⦄ ⦃ iOrdB : Ord b ⦄
                   → ⦃ IsLawfulOrd a ⦄ → ⦃ IsLawfulOrd b ⦄
                   → IsLawfulOrd (a × b)

  iLawfulOrdTuple₃ : ⦃ iOrdA : Ord a ⦄ ⦃ iOrdB : Ord b ⦄ ⦃ iOrdC : Ord c ⦄
                   → ⦃ IsLawfulOrd a ⦄ → ⦃ IsLawfulOrd b ⦄ → ⦃ IsLawfulOrd c ⦄
                   → IsLawfulOrd (a × b × c)

  iLawfulOrdList : ⦃ iOrdA : Ord a ⦄ → ⦃ IsLawfulOrd a ⦄ → IsLawfulOrd (List a)

  iLawfulOrdEither : ⦃ iOrdA : Ord a ⦄ → ⦃ iOrdB : Ord b ⦄ →  ⦃ IsLawfulOrd a ⦄ → ⦃ IsLawfulOrd b ⦄ → IsLawfulOrd (Either a b)