In this module we will define the delay monad, together with two notions of equality between computations, strong and weak bisimilarity. We will show that the setoid with weak bisimilarity extends to a monad (so does the one with strong bisimilarity, but this is not relevant for the later developments)
module Monad.Instance.Setoids.Delay {c ℓ} where
open Setoid using () renaming (Carrier to ∣_∣; _≈_ to [_][_≡_])
open module eq (S : Setoid c (c ⊔ ℓ)) = IsEquivalence (Setoid.isEquivalence S) using () renaming (refl to ≡-refl; sym to ≡-sym; trans to ≡-trans)
We start out by defining Delay as a mutual (co-)inductive type:
module _ (A : Set c) where
mutual
data Delay : Set c where
now : A → Delay
later : Delay′ → Delay
record Delay′ : Set c where
coinductive
constructor dela
field force : Delay
open Delay′ public
-- A non-terminating computation
never : Delay
never = later λ { .force → never }
-- Removes a later constructor, if possible.
drop-later : Delay → Delay
drop-later (now x) = now x
drop-later (later x) = force x
First we define strong bisimilarity and show that it is an equivalence relation:
module Bisimilarity (A : Setoid c (c ⊔ ℓ)) where
-- adapted from https://www.cse.chalmers.se/∼nad/listings/delay-monad/Delay-monad.Bisimilarity.html
mutual
data _∼_ : Delay ∣ A ∣ → Delay ∣ A ∣ → Set (c ⊔ ℓ) where
now∼ : ∀ {x y} → [ A ][ x ≡ y ] → now x ∼ now y
later∼ : ∀ {x y} → force x ∼′ force y → later x ∼ later y
record _∼′_ (x y : Delay ∣ A ∣) : Set (c ⊔ ℓ) where
coinductive
constructor delay∼
field force∼ : x ∼ y
open _∼′_ public
-- strong bisimilarity of now and later leads to a clash
now∼later : ∀ {ℓ'}{Z : Set ℓ'}{x : ∣ A ∣}{y : Delay′ ∣ A ∣} → now x ∼ later y → Z
now∼later ()
∼-refl : ∀ {x : Delay ∣ A ∣} → x ∼ x
∼-refl {now x} = now∼ (≡-refl A)
∼-refl {later x} = later∼ λ { .force∼ → ∼-refl }
∼-sym : ∀ {x y : Delay ∣ A ∣} → x ∼ y → y ∼ x
∼-sym (now∼ x≡y) = now∼ (≡-sym A x≡y)
∼-sym (later∼ fx∼fy) = later∼ λ { .force∼ → ∼-sym (force∼ fx∼fy) }
∼-trans : ∀ {x y z : Delay ∣ A ∣} → x ∼ y → y ∼ z → x ∼ z
∼-trans (now∼ x≡y) (now∼ y≡z) = now∼ (≡-trans A x≡y y≡z)
∼-trans (later∼ x∼y) (later∼ y∼z) = later∼ λ { .force∼ → ∼-trans (force∼ x∼y) (force∼ y∼z) }
Next we define weak-bisimilarity and proof some helper lemmas to finally show that it is an equivalence relation:
data _↓_ : Delay ∣ A ∣ → ∣ A ∣ → Set (c ⊔ ℓ) where
now↓ : ∀ {x y} (x≡y : [ A ][ x ≡ y ]) → now x ↓ y
later↓ : ∀ {x y} (x↓y : (force x) ↓ y) → later x ↓ y
unique↓ : ∀ {a : Delay ∣ A ∣ } {x y : ∣ A ∣} → a ↓ x → a ↓ y → [ A ][ x ≡ y ]
unique↓ (now↓ a≡x) (now↓ a≡y) = ≡-trans A (≡-sym A a≡x) a≡y
unique↓ (later↓ fb↓x) (later↓ fb↓y) = unique↓ fb↓x fb↓y
mutual
data _≈_ : Delay ∣ A ∣ → Delay ∣ A ∣ → Set (c ⊔ ℓ) where
↓≈ : ∀ {x y a b} (a≡b : [ A ][ a ≡ b ]) (x↓a : x ↓ a) (y↓b : y ↓ b) → x ≈ y
later≈ : ∀ {x y} (x≈y : force x ≈′ force y) → later x ≈ later y
record _≈′_ (x y : Delay ∣ A ∣) : Set (c ⊔ ℓ) where
coinductive
constructor delay≈
field force≈ : x ≈ y
open _≈′_ public
≡↓ : ∀ {x y : ∣ A ∣} {z : Delay ∣ A ∣} → [ A ][ x ≡ y ] → z ↓ x → z ↓ y
≡↓ {x} {y} {.(now _)} x≡y (now↓ a≡x) = now↓ (≡-trans A a≡x x≡y)
≡↓ {x} {y} {.(later _)} x≡y (later↓ z↓x) = later↓ (≡↓ x≡y z↓x)
≈↓ : ∀ {x y : Delay ∣ A ∣ } {a : ∣ A ∣} → x ≈ y → x ↓ a → y ↓ a
≈↓ (↓≈ c≡b (now↓ x≡c) y↓b) (now↓ x≡a) = ≡↓ (≡-trans A (≡-trans A (≡-sym A c≡b) (≡-sym A x≡c)) x≡a) y↓b
≈↓ (↓≈ c≡b (later↓ x↓c) y↓b) (later↓ x↓a) = ≡↓ (≡-trans A (≡-sym A c≡b) (≡-sym A (unique↓ x↓a x↓c))) y↓b
≈↓ (later≈ fx≈fy) (later↓ fx↓a) = later↓ (≈↓ (force≈ fx≈fy) fx↓a)
≈-refl : ∀ {x : Delay ∣ A ∣} → x ≈ x
≈-refl {now x} = ↓≈ (≡-refl A) (now↓ (≡-refl A)) (now↓ (≡-refl A))
≈-refl {later x} = later≈ λ { .force≈ → ≈-refl }
≈-sym : ∀ {x y : Delay ∣ A ∣} → x ≈ y → y ≈ x
≈-sym (↓≈ a≡b x↓a y↓b) = ↓≈ (≡-sym A a≡b) y↓b x↓a
≈-sym (later≈ x≈y) = later≈ λ { .force≈ → ≈-sym (force≈ x≈y) }
≈-trans : ∀ {x y z : Delay ∣ A ∣} → x ≈ y → y ≈ z → x ≈ z
≈-trans (↓≈ a≡b x↓a y↓b) (↓≈ c≡d y↓c z↓d) = ↓≈ (≡-trans A (≡-trans A a≡b (unique↓ y↓b y↓c)) c≡d) x↓a z↓d
≈-trans (↓≈ a≡b z↓a (later↓ x↓b)) (later≈ x≈y) = ↓≈ a≡b z↓a (later↓ (≈↓ (force≈ x≈y) x↓b))
≈-trans (later≈ x≈y) (↓≈ a≡b (later↓ y↓a) z↓b) = ↓≈ a≡b (later↓ (≈↓ (≈-sym (force≈ x≈y)) y↓a)) z↓b
≈-trans (later≈ x≈y) (later≈ y≈z) = later≈ λ { .force≈ → ≈-trans (force≈ x≈y) (force≈ y≈z) }
Additionally we can define a relation ≲ between computations where x ≲ y iff x terminates faster than y:
mutual
data _≲_ : Delay ∣ A ∣ → Delay ∣ A ∣ → Set (c ⊔ ℓ) where
↓≲ : ∀ {y a} (y↓a : y ↓ a) → now a ≲ y
later≲ : ∀ {x y} (x≈y : force x ≲′ force y) → later x ≲ later y
record _≲′_ (x y : Delay ∣ A ∣) : Set (c ⊔ ℓ) where
coinductive
constructor delay≲
field
force≲ : x ≲ y
open _≲′_ public
First we define the functor action and the monad multiplication. The
monad unit is of course the now constructor.
module DelayMonad where
-- The functor action of Delay
liftF : ∀ {A B : Set c} → (A → B) → Delay A → Delay B
liftF f (now x) = now (f x)
liftF f (later x) = later λ { .force → liftF f (force x) }
-- Monad multiplication
μ : ∀ {A : Setoid c (c ⊔ ℓ)} → Delay (Delay ∣ A ∣) → Delay ∣ A ∣
μ {A} (now x) = x
μ {A} (later x) = later λ { .force → μ {A} (force x) }
open DelayMonad
Some helpers for reasoning with setoid morphisms:
open Bisimilarity renaming (_≈_ to [_][_≈_]; _≈′_ to [_][_≈′_]; _∼_ to [_][_∼_]; _∼′_ to [_][_∼′_]; _↓_ to [_][_↓_]; _≲_ to [_][_≲_]; _≲′_ to [_][_≲′_])
open _⟶_ using (cong) renaming (to to <_>)
-- pointwise equality between setoid morphisms:
_≐_ : ∀ {c' ℓ'} {A B : Setoid c' ℓ'} → A ⟶ B → A ⟶ B → Set (c' ⊔ ℓ')
_≐_ {c'} {ℓ'} {A} {B} f g = Setoid._≈_ (A ⇨ B) f g
Next we show that (Delay, _∼_) is a monad:
module DelayMonad∼ where
private
Delay∼ : Setoid c (c ⊔ ℓ) → Setoid c (c ⊔ ℓ)
Delay∼ A = record { Carrier = Delay ∣ A ∣ ; _≈_ = [_][_∼_] A ; isEquivalence = record { refl = ∼-refl A ; sym = ∼-sym A ; trans = ∼-trans A } }
-- now is a setoid morphism
η∼ : ∀ (A : Setoid c (c ⊔ ℓ)) → A ⟶ Delay∼ A
η∼ A = record { to = now ; cong = nowF∼-cong }
where
nowF∼-cong : ∀ {A : Setoid c (c ⊔ ℓ)} {x y : ∣ A ∣} → [ A ][ x ≡ y ] → [ A ][ now x ∼ now y ]
nowF∼-cong {A} {x} {y} x≡y = now∼ x≡y
-- μ is a setoid morphism
μ∼ : ∀ (A : Setoid c (c ⊔ ℓ)) → Delay∼ (Delay∼ A) ⟶ Delay∼ A
μ∼ A = record { to = μ {A} ; cong = μ∼-cong A }
where
μ∼-cong : ∀ (A : Setoid c (c ⊔ ℓ)) {x y : Delay (Delay ∣ A ∣)} → [ Delay∼ A ][ x ∼ y ] → [ A ][ μ {A} x ∼ μ {A} y ]
μ∼-cong A {.(now _)} {.(now _)} (now∼ x∼y) = x∼y
μ∼-cong A {.(later _)} {.(later _)} (later∼ x∼y) = later∼ λ { .force∼ → μ∼-cong A (force∼ x∼y) }
-- liftF is a setoid-morphism
liftF∼ : ∀ {A B : Setoid c (c ⊔ ℓ)} → A ⟶ B → Delay∼ A ⟶ Delay∼ B
liftF∼ {A} {B} f = record { to = liftF < f > ; cong = liftF∼-cong }
where
liftF∼-cong : ∀ {x y} → [ A ][ x ∼ y ] → [ B ][ liftF < f > x ∼ liftF < f > y ]
liftF∼-cong {.(now _)} {.(now _)} (now∼ x≡y) = cong (η∼ B) (cong f x≡y)
liftF∼-cong {.(later _)} {.(later _)} (later∼ x∼y) = later∼ λ { .force∼ → liftF∼-cong (force∼ x∼y) }
-- η∼ is natural
η∼-natural : ∀ {A B : Setoid c (c ⊔ ℓ)} (f : A ⟶ B) → (η∼ B ∘ f) ≐ (liftF∼ f ∘ η∼ A)
η∼-natural {A} {B} f {x} = cong (η∼ B) (cong f (≡-refl A))
-- μ∼ is natural
μ∼-natural : ∀ {A B : Setoid c (c ⊔ ℓ)} (f : A ⟶ B) → (μ∼ B ∘ liftF∼ (liftF∼ f)) ≐ (liftF∼ f ∘ μ∼ A)
μ∼-natural {A} {B} f {now x} = ∼-refl B
μ∼-natural {A} {B} f {later x} = later∼ λ { .force∼ → μ∼-natural {A} {B} f {force x} }
-- liftF is a homomorphism
liftF∼-comp : ∀ {A B C : Setoid c (c ⊔ ℓ)} {f : A ⟶ B} {g : B ⟶ C} {x : Delay ∣ A ∣} → [ C ][ liftF (< g > ∘′ < f >) x ∼ (liftF < g > ∘′ liftF < f >) x ]
liftF∼-comp {A} {B} {C} {f} {g} {now x} = cong (η∼ C) (cong g (cong f (≡-refl A)))
liftF∼-comp {A} {B} {C} {f} {g} {later x} = later∼ λ { .force∼ → liftF∼-comp {A} {B} {C} {f} {g} {force x} }
-- liftF preserves identities
liftF∼-id : ∀ {A : Setoid c (c ⊔ ℓ)} → (liftF∼ (idₛ A)) ≐ (idₛ (Delay∼ A))
liftF∼-id {A} {now x} = ∼-refl A
liftF∼-id {A} {later x} = later∼ λ { .force∼ → liftF∼-id {A} }
-- liftF respects strong bisimilarity
liftF∼-resp : ∀ {A B : Setoid c (c ⊔ ℓ)} {f g : A ⟶ B} → f ≐ g → liftF∼ f ≐ liftF∼ g
liftF∼-resp {A} {B} {f} {g} f≐g {now x} = cong (η∼ B) f≐g
liftF∼-resp {A} {B} {f} {g} f≐g {later x} = later∼ λ { .force∼ → liftF∼-resp {A} {B} {f} {g} f≐g }
-- μ∼ is associative
μ∼-assoc : ∀ {A : Setoid c (c ⊔ ℓ)} {x : Delay (Delay (Delay ∣ A ∣))} → [ A ][ (μ∼ A ∘ (liftF∼ (μ∼ A))) ⟨$⟩ x ∼ (μ∼ A ∘ μ∼ (Delay∼ A)) ⟨$⟩ x ]
μ∼-assoc {A} {now x} = ∼-refl A
μ∼-assoc {A} {later x} = later∼ λ { .force∼ → μ∼-assoc {A} {force x} }
-- η∼ is a left identity of μ∼
identityˡ∼ : ∀ {A : Setoid c (c ⊔ ℓ)} {x : Delay ∣ A ∣} → [ A ][ (μ∼ A ∘ liftF∼ (η∼ A)) ⟨$⟩ x ∼ x ]
identityˡ∼ {A} {now x} = ∼-refl A
identityˡ∼ {A} {later x} = later∼ λ { .force∼ → identityˡ∼ {A} {force x} }
-- η∼ is a right identity of μ∼
identityʳ∼ : ∀ {A : Setoid c (c ⊔ ℓ)} → (μ∼ A ∘ η∼ (Delay∼ A)) ≐ idₛ (Delay∼ A)
identityʳ∼ {A} {now x} = ∼-refl A
identityʳ∼ {A} {later x} = ∼-refl A
delayMonad∼ : Monad (Setoids c (c ⊔ ℓ))
delayMonad∼ = record
{ F = record
{ F₀ = Delay∼
; F₁ = liftF∼
; identity = liftF∼-id
; homomorphism = λ {X} {Y} {Z} {f} {g} → liftF∼-comp {X} {Y} {Z} {f} {g}
; F-resp-≈ = λ {A} {B} {f} {g} → liftF∼-resp {A} {B} {f} {g}
}
; η = ntHelper (record { η = η∼ ; commute = η∼-natural })
; μ = ntHelper (record { η = μ∼ ; commute = μ∼-natural })
; assoc = λ {A} {x} → μ∼-assoc {A} {x}
; sym-assoc = λ {A} {x} → ∼-sym A (μ∼-assoc {A} {x})
; identityˡ = identityˡ∼
; identityʳ = identityʳ∼
}
open DelayMonad∼
open Monad delayMonad∼ using () renaming (F to Delay∼; η to η∼; μ to μ∼; assoc to assoc∼; sym-assoc to sym-assoc∼; identityˡ to identityˡ∼; identityʳ to identityʳ∼)
Then showing that (Delay, _≈_) is a monad is easy, since
the monad laws follow from strong bisimilarity:
module DelayMonad≈ where
private
Delay≈ : Setoid c (c ⊔ ℓ) → Setoid c (c ⊔ ℓ)
Delay≈ A = record { Carrier = Delay ∣ A ∣ ; _≈_ = [_][_≈_] A ; isEquivalence = record { refl = ≈-refl A ; sym = ≈-sym A ; trans = ≈-trans A } }
-- Strong bisimilarity implies weak bisimilarity
∼⇒≈ : ∀ {A : Setoid c (c ⊔ ℓ)} {x y : Delay ∣ A ∣} → [ A ][ x ∼ y ] → [ A ][ x ≈ y ]
∼⇒≈ {A} {.(now _)} {.(now _)} (now∼ a≡b) = ↓≈ a≡b (now↓ (≡-refl A)) (now↓ (≡-refl A))
∼⇒≈ {A} {.(later _)} {.(later _)} (later∼ x∼y) = later≈ λ { .force≈ → ∼⇒≈ (force∼ x∼y) }
-- force x is weakly bisimilar to later x
later-self : ∀ {A : Setoid c (c ⊔ ℓ)} {x : Delay′ ∣ A ∣} → [ A ][ force x ≈ later x ]
later-self {A} {x} with force x in eqx
... | now y = ↓≈ (≡-refl A) (now↓ (≡-refl A)) (later↓ helper)
where
helper : [ A ][ force x ↓ y ]
helper rewrite eqx = now↓ (≡-refl A)
... | later y = later≈ helper
where
helper : [ A ][ force y ≈′ force x ]
force≈ (helper) rewrite eqx = later-self {x = y}
-- now is injective
now-inj≈ : ∀ {A : Setoid c (c ⊔ ℓ)} {x y : ∣ A ∣} → [ A ][ now x ≈ now y ] → [ A ][ x ≡ y ]
now-inj≈ {A} {x} {y} (↓≈ a≡b (now↓ x≡a) (now↓ y≡b)) = ≡-trans A x≡a (≡-trans A a≡b (≡-sym A y≡b))
private
-- now is a setoid morphism
η≈ : ∀ (A : Setoid c (c ⊔ ℓ)) → A ⟶ Delay≈ A
η≈ A = record { to = now ; cong = now≈-cong }
where
now≈-cong : ∀ {A : Setoid c (c ⊔ ℓ)} {x y : ∣ A ∣} → [ A ][ x ≡ y ] → [ A ][ now x ≈ now y ]
now≈-cong {A} {x} {y} x≡y = ↓≈ x≡y (now↓ (≡-refl A)) (now↓ (≡-refl A))
-- liftF≈ is a setoid morphism
liftF≈ : ∀ {A B : Setoid c (c ⊔ ℓ)} → A ⟶ B → Delay≈ A ⟶ Delay≈ B
liftF≈ {A} {B} f = record { to = liftF < f > ; cong = liftF≈-cong f }
where
lift↓ : ∀ {A B : Setoid c (c ⊔ ℓ)} (f : A ⟶ B) {x : Delay ∣ A ∣} {b : ∣ A ∣} → [ A ][ x ↓ b ] → [ B ][ (liftF (< f >) x) ↓ (f ⟨$⟩ b) ]
lift↓ {A} {B} f {now x} {b} (now↓ x≡a) = now↓ (cong f x≡a)
lift↓ {A} {B} f {later x} {b} (later↓ x↓b) = later↓ (lift↓ f x↓b)
liftF≈-cong : ∀ {A B : Setoid c (c ⊔ ℓ)} (f : A ⟶ B) {x y : Delay ∣ A ∣} → [ A ][ x ≈ y ] → [ B ][ liftF < f > x ≈ liftF < f > y ]
liftF≈-cong {A} {B} f {now x} {now y} (↓≈ a≡b (now↓ x≡a) (now↓ y≡b)) = ↓≈ (cong f a≡b) (now↓ (cong f x≡a)) (now↓ (cong f y≡b))
liftF≈-cong {A} {B} f {now x} {later y} (↓≈ a≡b (now↓ x≡a) (later↓ y↓b)) = ↓≈ (cong f a≡b) (now↓ (cong f x≡a)) (later↓ (lift↓ f y↓b))
liftF≈-cong {A} {B} f {later x} {now y} (↓≈ a≡b (later↓ x↓a) (now↓ y≡b)) = ↓≈ (cong f a≡b) (later↓ (lift↓ f x↓a)) (now↓ (cong f y≡b))
liftF≈-cong {A} {B} f {later x} {later y} (↓≈ a≡b (later↓ x↓a) (later↓ y↓b)) = later≈ λ { .force≈ → liftF≈-cong f (↓≈ a≡b x↓a y↓b) }
liftF≈-cong {A} {B} f {later x} {later y} (later≈ x≈y) = later≈ λ { .force≈ → liftF≈-cong f (force≈ x≈y) }
-- liftF≈ respects weak bisimilarity
liftF≈-resp : ∀ {A B : Setoid c (c ⊔ ℓ)} {f g : A ⟶ B} → f ≐ g → liftF≈ f ≐ liftF≈ g
liftF≈-resp {A} {B} {f} {g} f≐g {now x} = cong (η≈ B) f≐g
liftF≈-resp {A} {B} {f} {g} f≐g {later x} = later≈ λ { .force≈ → liftF≈-resp {A} {B} {f} {g} f≐g }
-- μ is a setoid morphism
μ≈ : ∀ (A : Setoid c (c ⊔ ℓ)) → Delay≈ (Delay≈ A) ⟶ Delay≈ A
μ≈ A = record { to = μ {A} ; cong = μ-cong A }
where
μ↓ : ∀ {A : Setoid c (c ⊔ ℓ)} {x : Delay (Delay ∣ A ∣)} {y : Delay ∣ A ∣} → [ Delay≈ A ][ x ↓ y ] → [ A ][ (μ {A} x) ≈ y ]
μ↓ {A} {now x} {y} (now↓ x≡y) = x≡y
μ↓ {A} {later x} {later y} (later↓ x↓y) = later≈ λ { .force≈ → μ↓ {A} {force x} {force y} (≡↓ (Delay≈ A) (≈-sym A later-self) x↓y) }
μ↓ {A} {later x} {now y} (later↓ x↓y) = ≈-trans A (≈-sym A later-self) (↓≈ (≡-refl A) (μ↓-trans x↓y (now↓ (≡-refl A))) (now↓ (≡-refl A)))
where
μ↓-trans : ∀ {A : Setoid c (c ⊔ ℓ)} {x : Delay (Delay ∣ A ∣)} {y : Delay ∣ A ∣} {b : ∣ A ∣} → [ Delay≈ A ][ x ↓ y ] → [ A ][ y ↓ b ] → [ A ][ (μ {A} x) ↓ b ]
μ↓-trans {A} {now x} {y} {b} (now↓ x≡y) y↓b = ≈↓ A (≈-sym A x≡y) y↓b
μ↓-trans {A} {later x} {now y} {b} (later↓ x↓y) (now↓ y≡b) = later↓ (μ↓-trans x↓y (now↓ y≡b))
μ↓-trans {A} {later x} {later y} {b} (later↓ x↓y) (later↓ y↓b) = later↓ (μ↓-trans (≡↓ (Delay≈ A) (≈-sym A later-self) x↓y) y↓b)
μ-cong : ∀ (A : Setoid c (c ⊔ ℓ)) {x y : Delay (Delay ∣ A ∣)} → [ Delay≈ A ][ x ≈ y ] → [ A ][ μ {A} x ≈ μ {A} y ]
μ-cong A {now x} {now y} x≈y = now-inj≈ x≈y
μ-cong A {now x} {later y} (↓≈ a≡b (now↓ x≡a) (later↓ y↓b)) = ≈-trans A (≈-sym A (μ↓ (≡↓ (Delay≈ A) (≈-trans A (≈-sym A a≡b) (≈-sym A x≡a)) y↓b))) later-self
μ-cong A {later x} {now y} (↓≈ a≡b (later↓ x↓a) (now↓ y≡b)) = ≈-trans A (≈-sym A later-self) (μ↓ (≡↓ (Delay≈ A) (≈-trans A a≡b (≈-sym A y≡b)) x↓a))
μ-cong A {later x} {later y} (↓≈ a≡b (later↓ x↓a) (later↓ y↓b)) = later≈ λ { .force≈ → μ-cong A (↓≈ a≡b x↓a y↓b) }
μ-cong A {later x} {later y} (later≈ x≈y) = later≈ λ { .force≈ → μ-cong A (force≈ x≈y) }
delayMonad≈ : Monad (Setoids c (c ⊔ ℓ))
delayMonad≈ = record
{ F = record
{ F₀ = Delay≈
; F₁ = liftF≈
; identity = ∼⇒≈ Delay∼.identity
; homomorphism = λ {X} {Y} {Z} {f} {g} → ∼⇒≈ (Delay∼.homomorphism {X} {Y} {Z} {f} {g})
; F-resp-≈ = λ {A} {B} {f} {g} → liftF≈-resp {A} {B} {f} {g}
}
; η = ntHelper (record { η = η≈ ; commute = λ f → ∼⇒≈ (NaturalTransformation.commute η∼ f) })
; μ = ntHelper (record { η = μ≈ ; commute = λ f {x} → ∼⇒≈ (NaturalTransformation.commute μ∼ f {x}) })
; assoc = λ {A} {x} → ∼⇒≈ (μ-assoc∼' {A} {x})
; sym-assoc = λ {A} {x} → ≈-sym A (∼⇒≈ (μ-assoc∼' {A} {x}))
; identityˡ = ∼⇒≈ identityˡ∼
; identityʳ = ∼⇒≈ identityʳ∼
}
where
-- Associativity needs this simple type variation to work:
μ-assoc∼' : ∀ {A : Setoid c (c ⊔ ℓ)} {x : Delay (Delay (Delay ∣ A ∣))} → [ A ][ (μ≈ A ∘ (liftF≈ (μ≈ A))) ⟨$⟩ x ∼ (μ≈ A ∘ μ≈ (Delay≈ A)) ⟨$⟩ x ]
μ-assoc∼' {A} {now x} = ∼-refl A
μ-assoc∼' {A} {later x} = later∼ (λ { .force∼ → μ-assoc∼' {A} {force x} })
open DelayMonad≈
open Monad delayMonad≈ using () renaming (F to Delay≈; η to η≈; μ to μ≈; assoc to assoc≈; sym-assoc to sym-assoc≈; identityˡ to identityˡ≈; identityʳ to identityʳ≈)
-- Universe polymorphic definition of natural numbers together with the setoid on ℕ with propositional equality
module nat {ℓ} where
data ℕ : Set ℓ where
zero : ℕ
suc : ℕ → ℕ
ℕ-setoid : Setoid ℓ ℓ
ℕ-setoid = record
{ Carrier = ℕ
; _≈_ = _≡_
; isEquivalence = Eq.isEquivalence
}
suc-inj : ∀ {n m} → suc n ≡ suc m → n ≡ m
suc-inj Eq.refl = Eq.refl
open nat
Finally some extra lemmas and definitions concerning ≲ and ≈.
module extra {A : Setoid c (c ⊔ ℓ)} where
-- ≲ implies weak bisimilarity
≲→≈ : {x y : Delay ∣ A ∣} → [ A ][ x ≲ y ] → [ A ][ x ≈ y ]
≲→≈ (↓≲ y↓a) = ↓≈ (≡-refl A) (now↓ (≡-refl A)) y↓a
≲→≈ (later≲ x≲y) = later≈ λ { .force≈ → ≲→≈ (force≲ x≲y) }
-- Race two computations and return the first one finished (preferring the left one)
race : Delay ∣ A ∣ → Delay ∣ A ∣ → Delay ∣ A ∣
race (now a) _ = now a
race (later x) (now a) = now a
race (later x) (later y) = later λ { .force → race (force x) (force y) }
-- If x and y are strongly bisimilar then racing is symmetric
race-sym∼ : ∀ {x y} → [ A ][ x ∼ y ] → [ A ][ race x y ∼ race y x ]
race-sym∼ {now x} {now y} x∼y = x∼y
race-sym∼ {now x} {later y} x∼y = ∼-refl A
race-sym∼ {later x} {now y} x∼y = ∼-refl A
race-sym∼ {later x} {later y} (later∼ x∼y) = later∼ λ { .force∼ → race-sym∼ (force∼ x∼y) }
-- If x and y are weakly bisimilar then racing is symmetric
race-sym≈ : ∀ {x y} → [ A ][ x ≈ y ] → [ A ][ race x y ∼ race y x ]
race-sym≈ {now x} {now y} (↓≈ a≡b (now↓ x≡a) (now↓ y≡b)) = now∼ (≡-trans A x≡a (≡-trans A a≡b (≡-sym A y≡b)))
race-sym≈ {now x} {later y} x≈y = ∼-refl A
race-sym≈ {later x} {now y} x≈y = ∼-refl A
race-sym≈ {later x} {later y} (↓≈ a≡b (later↓ x↓a) (later↓ y↓b)) = later∼ λ { .force∼ → race-sym≈ (↓≈ a≡b x↓a y↓b) }
race-sym≈ {later x} {later y} (later≈ x≈y) = later∼ λ { .force∼ → race-sym≈ (force≈ x≈y) }
-- If x and y are weakly bisimilar then `race x y ≲ y`
≈→≲ : {x y : Delay ∣ A ∣} → [ A ][ x ≈ y ] → [ A ][ race x y ≲ y ]
≈→≲ (later≈ x≈y) = later≲ λ { .force≲ → ≈→≲ (force≈ x≈y) }
≈→≲ (↓≈ a≡b x↓a y↓b) = ≈→≲₀ x↓a y↓b a≡b
where
≈→≲₀ : ∀ {x y a b} (x↓a : [ A ][ x ↓ a ]) (y↓b : [ A ][ y ↓ b ]) (a≡b : [ A ][ a ≡ b ]) → [ A ][ race x y ≲ y ]
≈→≲₀ (now↓ x≡a) y↓b a≡b = ↓≲ (≡↓ A (≡-sym A (≡-trans A x≡a a≡b)) y↓b)
≈→≲₀ (later↓ x↓a) (now↓ x≡y) a≡b = ↓≲ (now↓ (≡-refl A))
≈→≲₀ (later↓ x↓a) (later↓ y↓b) a≡b = later≲ (record { force≲ = ≈→≲₀ x↓a y↓b a≡b })
-- Returns the steps a terminating computation has to take
delta₀ : {x : Delay ∣ A ∣} {a : ∣ A ∣} → (x↓a : [ A ][ x ↓ a ]) → ℕ {c}
delta₀ (now↓ x≡y) = zero
delta₀ (later↓ x↓a) = suc (delta₀ x↓a)
-- If we know that x terminates before y we can run x and remember the amount of steps
delta : {x y : Delay ∣ A ∣} → [ A ][ x ≲ y ] → Delay (∣ A ∣ × ℕ {c})
delta (↓≲ {x} {a} x↓a) = now (a , delta₀ x↓a)
delta (later≲ x≲′y) = later λ { .force → delta (force≲ x≲′y) }
-- Adds `n` later constructors to a computation
ι : ∣ A ∣ × ℕ {c} → Delay ∣ A ∣
ι (x , zero) = now x
ι (x , suc n) = later λ { .force → ι (x , n) }
-- ι is a setoid morphism (wrt strong bisimilarity)
ι∼ : (A ×ₛ (ℕ-setoid {c})) ⟶ Delay∼.₀ A
ι∼ = record { to = ι ; cong = ι-cong }
where
ι-cong : ∀ {x y} → [ A ×ₛ (ℕ-setoid {c}) ][ x ≡ y ] → [ A ][ ι x ∼ ι y ]
ι-cong {x , zero} {y , zero} (x≡y , n≡m) = now∼ x≡y
ι-cong {x , suc n} {y , suc m} (x≡y , n≡m) = later∼ λ { .force∼ → ι-cong (x≡y , (suc-inj n≡m)) }
-- Properties of _≲_
delta-prop₁ : {x y : Delay ∣ A ∣} (x≲y : [ A ][ x ≲ y ]) → [ A ][ liftF proj₁ (delta x≲y) ∼ x ]
delta-prop₁ {.(now _)} {x} (↓≲ x↓a) = now∼ (≡-refl A)
delta-prop₁ {.(later _)} {.(later _)} (later≲ x≲y) = later∼ λ { .force∼ → delta-prop₁ (force≲ x≲y) }
delta-prop₂ : {x y : Delay ∣ A ∣} (x≲y : [ A ][ x ≲ y ]) → [ A ][ μ {A} (liftF ι (delta x≲y)) ∼ y ]
delta-prop₂ (later≲ x≲y) = later∼ λ { .force∼ → delta-prop₂ (force≲ x≲y) }
delta-prop₂ (↓≲ x↓a) = ∼-sym A (ι↓ x↓a)
where
ι↓ : {x : Delay ∣ A ∣}{a : ∣ A ∣} → (x↓a : [ A ][ x ↓ a ]) → [ A ][ x ∼ ι (a , delta₀ x↓a) ]
ι↓ {.(now _)} {a} (now↓ x≡y) = now∼ x≡y
ι↓ {.(later _)} {a} (later↓ x↓a) = later∼ (record { force∼ = ι↓ x↓a })