{-# OPTIONS --rewriting --allow-unsolved-metas #-}

module Calf.Directed where

open import Calf.Prelude
open import Calf.CBPV
open import Relation.Binary.PropositionalEquality

open import Relation.Binary.Core
open import Relation.Binary.Definitions
open import Relation.Binary.Structures

-- Directed ordering on positive types.

infix 4 _≤⁺_
postulate
  _≤⁺_ : val A  val A  
  ≤⁺-isPreorder : IsPreorder _≡_ (_≤⁺_ {A})

  ≤⁺-mono : (f : val A  val B) 
    f Preserves (_≤⁺_ {A})  (_≤⁺_ {B})

≤⁺-reflexive : _≡_  _≤⁺_ {A}
≤⁺-reflexive = IsPreorder.reflexive ≤⁺-isPreorder

≤⁺-refl : Reflexive (_≤⁺_ {A})
≤⁺-refl = IsPreorder.refl ≤⁺-isPreorder

≤⁺-trans : Transitive (_≤⁺_ {A})
≤⁺-trans = IsPreorder.trans ≤⁺-isPreorder

≤⁺-mono₂ : (f : val A  val B  val C) 
  f Preserves₂ (_≤⁺_ {A})  (_≤⁺_ {B})  (_≤⁺_ {C})
≤⁺-mono₂ f a≤a' b≤b' =
  ≤⁺-trans
  (≤⁺-mono (f _) b≤b')
  (≤⁺-mono  a  f a _) a≤a')

≤⁺-syntax : val A  val A  
≤⁺-syntax {A} = _≤⁺_ {A}

syntax ≤⁺-syntax {A} a a' = a ≤⁺[ A ] a'


-- Directed ordering on negative types.
-- Since `cmp X = val (U X)`, derived form in terms of ordering on positive types.

infix 4 _≤⁻_
_≤⁻_ : cmp X  cmp X  
_≤⁻_ {X} e e' = e ≤⁺[ U X ] e'

≤⁻-isPreorder : IsPreorder _≡_ (_≤⁻_ {X})
≤⁻-isPreorder {X} =
  record
    { isEquivalence = IsPreorder.isEquivalence (≤⁺-isPreorder {U X})
    ; reflexive = ≤⁺-reflexive
    ; trans = ≤⁺-trans
    }

≤⁻-mono : (f : cmp X  cmp Y) 
  f Preserves (_≤⁻_ {X})  (_≤⁻_ {Y})
≤⁻-mono = ≤⁺-mono

≤⁻-mono₂ : (f : cmp X  cmp Y  cmp Z) 
  f Preserves₂ (_≤⁻_ {X})  (_≤⁻_ {Y})  (_≤⁻_ {Z})
≤⁻-mono₂ = ≤⁺-mono₂

postulate
  λ-mono-≤⁻ : {X : val A  tp⁻} {f f' : (a : val A)  cmp (X a)}
     ((a : val A)  _≤⁻_ {X a} (f a) (f' a))
     _≤⁻_ {Π A X} f f'

≤⁻-reflexive : _≡_  _≤⁻_ {X}
≤⁻-reflexive = IsPreorder.reflexive ≤⁻-isPreorder

≤⁻-refl : Reflexive (_≤⁻_ {X})
≤⁻-refl = IsPreorder.refl ≤⁻-isPreorder

≤⁻-trans : Transitive (_≤⁻_ {X})
≤⁻-trans = IsPreorder.trans ≤⁻-isPreorder

≤⁻-syntax : cmp X  cmp X  
≤⁻-syntax {X} = _≤⁻_ {X}

syntax ≤⁻-syntax {X} e e' = e ≤⁻[ X ] e'


bind-mono-≤⁻ : {e e' : cmp (F A)} {f f' : val A  cmp X}
   e ≤⁻[ F A ] e'
   f ≤⁻[ Π A  _  X) ] f'
   (bind {A} X e f) ≤⁻[ X ] (bind {A} X e' f')
bind-mono-≤⁻ {A} {X} {e' = e'} {f} {f'} e≤e' f≤f' =
  ≤⁻-trans
    (≤⁻-mono  e  bind {A} X e f) e≤e')
    (≤⁻-mono {Π A  _  X)} {X} (bind {A} X e') {f} {f'} f≤f')

bind-monoˡ-≤⁻ : {e e' : cmp (F A)} (f : val A  cmp X)
   e ≤⁻[ F A ] e'
   (bind {A} X e f) ≤⁻[ X ] (bind {A} X e' f)
bind-monoˡ-≤⁻ f e≤e' = bind-mono-≤⁻ e≤e' ≤⁻-refl

bind-monoʳ-≤⁻ : (e : cmp (F A)) {f f' : val A  cmp X}
   ((a : val A)  (f a) ≤⁻[ X ] (f' a))
   (bind {A} X e f) ≤⁻[ X ] (bind {A} X e f')
bind-monoʳ-≤⁻ e f≤f' = bind-mono-≤⁻ (≤⁻-refl {x = e}) (λ-mono-≤⁻ f≤f')

bind-irr-mono-≤⁻ : {e₁ e₁' : cmp (F A)} {e₂ e₂' : cmp X}
   e₁ ≤⁻[ F A ] e₁'
   e₂ ≤⁻[ X ] e₂'
   (bind {A} X e₁ λ _  e₂) ≤⁻[ X ] (bind {A} X e₁' λ _  e₂')
bind-irr-mono-≤⁻ e₁≤e₁' e₂≤e₂' =
  bind-mono-≤⁻ e₁≤e₁' (λ-mono-≤⁻ λ a  e₂≤e₂')

bind-irr-monoˡ-≤⁻ : {e₁ e₁' : cmp (F A)} {e₂ : cmp X}
   e₁ ≤⁻[ F A ] e₁'
   (bind {A} X e₁ λ _  e₂) ≤⁻[ X ] (bind {A} X e₁' λ _  e₂)
bind-irr-monoˡ-≤⁻ e₁≤e₁' =
  bind-irr-mono-≤⁻ e₁≤e₁' ≤⁻-refl


open import Level using (0ℓ)
open import Relation.Binary using (Preorder)
open import Relation.Binary.Structures

≤⁻-preorder : tp⁻  Preorder 0ℓ 0ℓ 0ℓ
Preorder.Carrier (≤⁻-preorder X) = cmp X
Preorder._≈_ (≤⁻-preorder X) = _≡_
Preorder._≲_ (≤⁻-preorder X) = _≤⁻_ {X}
Preorder.isPreorder (≤⁻-preorder X) = ≤⁻-isPreorder {X}

module ≤⁻-Reasoning (X : tp⁻) where
  open import Relation.Binary.Reasoning.Preorder (≤⁻-preorder X) public