{-# OPTIONS --safe --experimental-lossy-unification #-}
open import Prelude
open import Signatures
open import FinitenessConditions
open import FreeMonad.PackagedTheory
module Hoare.Lemmas {ℓ} (𝒯 : FullTheory ℓ) where
open import FreeMonad.Quotiented 𝒯
open import Hoare.Definition 𝒯
open import Truth
sef-dsef-cont : ∀ {B : Type b} → (ps : Σ[ p ⦂ Term A ] × SEF b p × DET b p) → (k : A → A → Term B) → (do x ← ps .fst ; y ← ps .fst ; k x y) ≡ (do x ← ps .fst ; k x x)
sef-dsef-cont (p , s , d) k = d k ; x ⇐ p ;/ s (k x x)
module _ {A : Type a} where
dsef-alt : (p : Term A)
→ DET (ℓsuc a) p
→ (do x ← p ; y ← p ; return (x |≡| y)) ≡ (do p ; p ; return True)
dsef-alt p d = d (λ x y → return (x |≡| y)) ; x ⇐ p ;/ _ ⇐ p ;/ cong return (proves ∣ refl ∣)
module _ {B : Type b} where
sef-com : (p : Term A) (xs : Term B) → SEF b p →
(do x ← xs ; p ; return x) ≡ (do p ; xs)
sef-com p xs sef⟨p⟩ =
(do x ← xs
p
return x) ≡⟨ x ⇐ xs ;/ sef⟨p⟩ (return x) ⟩
(do x ← xs
return x) ≡⟨ >>=-idʳ _ ⟩
xs ≡˘⟨ sef⟨p⟩ xs ⟩
(do p
xs) ∎
_⟪_⟫_ : Term A → (A → B → C) → Term B → Term C
xs ⟪ f ⟫ ys = do x ← xs ; y ← ys ; return (f x y)
infixl 6 _⟨∧⟩_
_⟨∧⟩_ : Term (Ω a) → Term (Ω a) → Term (Ω a)
xs ⟨∧⟩ ys = xs ⟪ _|∧|_ ⟫ ys
infixl 5 _⟨∨⟩_
_⟨∨⟩_ : Term (Ω a) → Term (Ω a) → Term (Ω a)
xs ⟨∨⟩ ys = xs ⟪ _|∨|_ ⟫ ys
⟪assoc⟫ : ∀ {d} {D : Type d} → (xs : Term A) (ys : Term B) (f : A → B → C) (k : C → Term D) →
(xs ⟪ f ⟫ ys) >>= k ≡ (do x ← xs ; y ← ys ; k (f x y))
⟪assoc⟫ xs ys f k = assoc xs _ _ ; x ⇐ xs ;/ assoc ys _ _
_⟪,⟫_ : Term A → Term B → Term (A × B)
_⟪,⟫_ = _⟪ _,_ ⟫_
assoc-⟪,⟫ : (xs : Term A) (ys : Term B) (k : A → B → Term C) →
(xs ⟪,⟫ ys) >>= uncurry k ≡ (do x ← xs ; y ← ys ; k x y)
assoc-⟪,⟫ xs ys k = ⟪assoc⟫ xs ys _,_ (uncurry k)
sef-<$> : (f : A → B) (p : Term A) → SEF c p → SEF c (f <$> p)
sef-<$> f p s k =
(f <$> p) >> k ≡⟨ assoc p _ _ ⟩
p >> k ≡⟨ s k ⟩
k ∎
det-<$> : (f : A → B) (p : Term A) → DET c p → DET c (f <$> p)
det-<$> f p s k =
(do x ← f <$> p; y ← f <$> p; k x y) ≡⟨ assoc p _ _ ⟩
(do x ← p; y ← f <$> p; k (f x) y) ≡⟨ x ⇐ p ;/ assoc p _ _ ⟩
(do x ← p; y ← p; k (f x) (f y)) ≡⟨ s (λ x y → k (f x) (f y)) ⟩
(do x ← p; p; k (f x) (f x)) ≡˘⟨ x ⇐ p ;/ assoc p _ _ ⟩
(do x ← p; f <$> p; k (f x) (f x)) ≡˘⟨ assoc p _ _ ⟩
(do x ← f <$> p; f <$> p; k x x) ∎
sef-⟪,⟫ : (p : Term A) (q : Term B) →
SEF c p → SEF c q → SEF c (p ⟪,⟫ q)
sef-⟪,⟫ p q sp sq k =
(p ⟪,⟫ q) >> k ≡⟨ assoc-⟪,⟫ p q _ ⟩
p >> q >> k ≡⟨ cong (p >>_) (sq k) ⟩
p >> k ≡⟨ sp k ⟩
k ∎
sef-com′ : (p : Term A) (q : Term B)
→ SEF c p → SEF c q
→ DET c (p ⟪,⟫ q) → {R : Type c} (k : A → B → Term R) →
(do x ← p ; y ← q ; k x y) ≡ (do y ← q ; x ← p ; k x y)
sef-com′ p q sp sq dpq k =
(do x ← p ; y ← q ; k x y) ≡˘⟨ assoc-⟪,⟫ p q _ ⟩
(do xy ← p ⟪,⟫ q ; uncurry k xy) ≡˘⟨ sef-dsef-cont (p ⟪,⟫ q , sef-⟪,⟫ p q sp sq , dpq) (λ xy xy′ → k (xy′ .fst) (xy .snd)) ⟩
(do xy ← p ⟪,⟫ q ; xy′ ← p ⟪,⟫ q ; k (xy′ .fst) (xy .snd)) ≡⟨ assoc-⟪,⟫ p q _ ⟩
(do _ ← p ; y ← q ; xy′ ← p ⟪,⟫ q ; k (xy′ .fst) y) ≡⟨ sp _ ⟩
(do y ← q ; xy′ ← p ⟪,⟫ q ; k (xy′ .fst) y) ≡⟨ y ⇐ q ;/ assoc-⟪,⟫ p q _ ⟩
(do y ← q ; x ← p ; _ ← q ; k x y) ≡⟨ y ⇐ q ;/ x ⇐ p ;/ sq (k x y) ⟩
(do y ← q ; x ← p ; k x y) ∎
⟨∧⟩-assoc : (x y z : Term (Ω a)) → (x ⟨∧⟩ y) ⟨∧⟩ z ≡ x ⟨∧⟩ (y ⟨∧⟩ z)
⟨∧⟩-assoc x y z =
(x ⟨∧⟩ y) ⟨∧⟩ z ≡⟨⟩
(do xy ← (x ⟨∧⟩ y); z′ ← z; return (xy |∧| z′)) ≡⟨ assoc x _ _ ⟩
(do x′ ← x; xy ← (do y′ ← y; return (x′ |∧| y′)); z′ ← z; return (xy |∧| z′)) ≡⟨ x′ ⇐ x ;/ assoc y _ _ ⟩
(do x′ ← x; y′ ← y; z′ ← z; return ((x′ |∧| y′) |∧| z′)) ≡⟨ x′ ⇐ x ;/ y′ ⇐ y ;/ z′ ⇐ z ;/ cong return ((λ { ((x , y) , z) → x , y , z }) iff λ { (x , y , z) → (x , y) , z }) ⟩
(do x′ ← x; y′ ← y; z′ ← z; return (x′ |∧| (y′ |∧| z′))) ≡˘⟨ x′ ⇐ x ;/ assoc y _ _ ; y′ ⇐ y ;/ assoc z _ _ ⟩
(do x′ ← x; yz ← (y ⟨∧⟩ z); return (x′ |∧| yz)) ≡⟨⟩
x ⟨∧⟩ (y ⟨∧⟩ z) ∎