Codata.streamBisim
import Core.prelude (id, ∘)
import Core.equality (cong)
import Codata.stream (stream, hd, tl, map)
import Codata.streamEq (tlN, nth, obsEq, obsEqRefl, nthMap, mapIdObsEq, mapFuseObsEq)
bisim : {a : 𝕌} → stream a → stream a → Ω
bisim =
λa s t. ∥(r : stream a → stream a → Ω)
× ((x y : stream a) → r x y → (hd x ≡ hd y) × r (tl x) (tl y)) × r s t∥
bisimHd : {a : 𝕌} {s t : stream a} → bisim s t → hd s ≡ hd t using (Codata.streamBisim.bisim.unfold)
bisimHd = λa s t h. squash-elim h (w. w .π₂ .π₁ s t (w .π₂ .π₂) .π₁)
bisimTl : {a : 𝕌} {s t : stream a} → bisim s t → bisim (tl s) (tl t)
using (Codata.streamBisim.bisim.unfold)
bisimTl = λa s t h. squash-elim h (w. ⋆ (w .π₁, w .π₂ .π₁, w .π₂ .π₁ s t (w .π₂ .π₂) .π₂))
bisimRefl : {a : 𝕌} (s : stream a) → bisim s s using (Codata.streamBisim.bisim.unfold)
bisimRefl =
λa s. ⋆
(λx y. x ≡ y), (λx y p. cong (λv. a) (λv. hd {} a v) p, cong (λv. stream a) (λv. tl v) p), ⋆
obsEqBisim : {a : 𝕌} {s t : stream a} → obsEq s t → bisim s t
using (Codata.stream.hd.eq,
Codata.stream.stream.unfold,
Codata.stream.tl.eq,
Codata.streamBisim.bisim.unfold,
Codata.streamEq.nth.eq,
Codata.streamEq.obsEq.unfold,
Codata.streamEq.tlN.eq)
obsEqBisim =
λa s t h. ⋆
(λx y. obsEq x y), (λx y p. squash-elim p (w. w Z), squash-elim p (w. ⋆ (λn. w (S n)))), h
bisimObsEq : {a : 𝕌} {s t : stream a} → bisim s t → obsEq s t
using (Codata.stream.hd.eq,
Codata.stream.stream.unfold,
Codata.stream.tl.eq,
Codata.streamBisim.bisim.unfold,
Codata.streamEq.nth.eq,
Codata.streamEq.obsEq.unfold,
Codata.streamEq.tlN.eq)
bisimObsEq =
λa s t h. ⋆
λn. ℕ-elim
m. (x y : stream a) → bisim x y → nth m x ≡ nth m y
λx y g. bisimHd g
m ih. λx y g. ih (tl x) (tl y) (bisimTl g)
n
s
t
h
mapIdBisim : {a : 𝕌} (s : stream a) → bisim (map (id {a}) s) s
using (Codata.streamBisim.bisim.unfold, Core.prelude.id.eq)
mapIdBisim = λa s. obsEqBisim (mapIdObsEq s)
bisimReflect : {a : 𝕌} {s t : stream a} → bisim s t → s ≡ t
using (bisim.eq,
hyp.rw,
Codata.stream.hd.eq,
Codata.stream.stream.eq,
Codata.stream.stream.unfold,
Codata.stream.tl.eq,
Codata.streamBisim.bisim.unfold)
bisimReflect = λa s t h. coind (x y. bisim x y) h (x y hb. ⋆ (bisimHd hb, bisimTl hb))
obsEqReflect : {a : 𝕌} {s t : stream a} → obsEq s t → s ≡ t
obsEqReflect = λa s t h. bisimReflect (obsEqBisim h)
mapIdEq : (a : 𝕌) (s : stream a) → map (id {a}) s ≡ s using (Core.prelude.id.eq)
mapIdEq = λa s. bisimReflect (mapIdBisim s)
mapFuseEq : (a b c : 𝕌) (f : a → b) (g : b → c) (s : stream a) → map g (map f s) ≡ map (g ∘ f) s
mapFuseEq = λa b c f g s. obsEqReflect (mapFuseObsEq f g s)