Skip to content
Snippets Groups Projects
Delay.agda 5.54 KiB
Newer Older
{-# OPTIONS --cubical --rewriting --guarded #-}
{-# OPTIONS --guardedness #-}
{-# OPTIONS -W noUnsupportedIndexedMatch #-}

 -- to allow opening this module in other files while there are still holes
{-# OPTIONS --allow-unsolved-metas #-}


open import Common.Later
open import Common.Common

module Semantics.Adequacy.Coinductive.Delay where

open import Cubical.Foundations.Prelude
open import Cubical.Foundations.Function
open import Cubical.Data.Sum
open import Cubical.Data.Unit renaming (Unit to ⊤)
open import Cubical.Data.Sigma
open import Cubical.Data.Nat -- renaming (ℕ to Nat) hiding (_·_ ; _^_)
open import Cubical.Foundations.Isomorphism
open import Cubical.Foundations.Structure
open import Cubical.Data.Empty as ⊥
open import Cubical.Relation.Nullary
open import Cubical.Foundations.Path

import Cubical.Data.Equality as Eq

open import Cubical.Foundations.HLevels


private
  variable
    ℓ : Level
    X : Type ℓ


record Delay (Res : Type ℓ) : Type ℓ

data State (Res : Type ℓ) : Type ℓ where
  done : Res -> State Res
  running : Delay Res -> State Res

record Delay Res where
  coinductive
  field view : State Res

open Delay public


-- Turn a State into a Delay.
fromState : State X → Delay X
view (fromState s) = s

-- The delay that returns the given value of type X in one step.
doneD : X -> Delay X
doneD x = fromState (done x)


-- Given a Delay d, returns the Delay d' that takes runs for one step
-- and then behaves as d.
stepD : Delay X -> Delay X
stepD d = fromState (running d)


-- An alternative definition of the Delay type using functions from natural numbers
-- to X ⊎ Unit that are defined at most once.
module Alternative (X : Type ℓ) where

  -- Given a Delay d, return a function on nats that, when d ≡ running ^ n (done x),
  -- maps n to inl x and every other number to inr tt.
  fromDelay : Delay X → (ℕ → X ⊎ Unit)
  fromDelay d n with d .view
--      f d n       | done x  = inl x
  fromDelay d zero    | done x = inl x
  fromDelay d (suc n) | done x = inr tt
  fromDelay d zero    | running _ = inr tt
  fromDelay d (suc n) | running d' = fromDelay d' n

  -- Given a function f on nats, return a delay that runs for n0 steps and returns x,
  -- where n0 is the smallest nat such that f n0 = inl x.
  toDelay : (ℕ → X ⊎ Unit) → Delay X
  toDelay f .view with f zero
  ... | inl x  = done x
  ... | inr tt = running (toDelay λ n → f (suc n))

  retr : (d : Delay X) → toDelay (fromDelay d) ≡ d
  retr d i .view with d .view
  ... | done x  = done x
  ... | running d' = running (retr d' i)


  PreDelay' : Type ℓ
  PreDelay' = ℕ -> (X ⊎ Unit)

  Delay' : Type ℓ
  Delay' = Σ[ f ∈ PreDelay' ] fromDelay (toDelay f) ≡ f


  terminatesWith : PreDelay' -> X -> Type ℓ
  terminatesWith d x = Σ[ n ∈ ℕ ] d n ≡ inl x

  terminates : PreDelay' -> Type ℓ
  terminates d = Σ[ n ∈ ℕ ] Σ[ x ∈ X ] d n ≡ inl x

  -- We can characterize the functions f for which fromDelay (toDelay f) ≡ f
  -- These are the functions that are defined at most once, i.e.,
  -- if f n ≡ inl x and f m ≡ inl x', then n ≡ m
  -- This is needed for showing that terminatesWith is a Prop.
  
  fromDelay-def-atmost-once : (d : Delay X) (n m : ℕ) -> (x x' : X) ->
    fromDelay d n ≡ inl x -> fromDelay d m ≡ inl x' -> n ≡ m
  fromDelay-def-atmost-once d n m x x' eq1 eq2 with n | m | d .view
  ... | zero   | zero   | done x = refl
  ... | suc n' | suc m' | running d' =
    cong suc (fromDelay-def-atmost-once d' n' m' x x' eq1 eq2)

  -- Impossible cases
  ... | n      | suc m' | done x = ⊥.rec (inl≠inr _ _ (sym eq2))
  ... | suc n' | m      | done x = ⊥.rec (inl≠inr _ _ (sym eq1))
  
  ... | zero   | m    | running d' = ⊥.rec (inl≠inr _ _ (sym eq1))
  ... | n      | zero | running d' = ⊥.rec (inl≠inr _ _ (sym eq2))


  delay'-necessary : (f : Delay') -> (n m : ℕ) (x x' : X) ->
    (fst f n ≡ inl x) -> (fst f m ≡ inl x') -> (n ≡ m)
  delay'-necessary f n m x x' eq1 eq2 = fromDelay-def-atmost-once
    (toDelay (fst f)) n m x x'
    ((λ i -> snd f i n) ∙ eq1) ((λ i -> snd f i m) ∙ eq2)

  -- Can also formulate the converse implication (TODO)
  delay'-sufficient : (f : PreDelay') ->
    ((n m : ℕ) (x x' : X) ->
     (f n ≡ inl x) -> (f m ≡ inl x') -> (n ≡ m)) ->
    fromDelay (toDelay f) ≡ f
  delay'-sufficient f H = {!!}

  -- Given a delay d, convert it to a function f using fromDelay,
  -- satisfying the condition that fromDelay (toDelay f) ≡ f.
  -- This condition is trivially satisfied since we have
  -- fromDelay (toDelay (fromDelay d)) ≡ fromDelay d
  -- (using the retraction property).
  Delay→Fun : (d : Delay X) -> Delay'
  fst (Delay→Fun d) = fromDelay d
  snd (Delay→Fun d) = cong fromDelay (retr d)
    

  isProp-terminatesWith : (d : Delay') (x : X) -> isProp (terminatesWith (fst d) x)
  isProp-terminatesWith d x = {!!}

  -- "Constructors" for Delay' corresponding to done and running
  delayFunDone : (x : X) -> Delay'
  delayFunDone x = {!!}
    where
      delayFunDone' : (x : X) -> PreDelay'
      delayFunDone' x zero = inl x
      delayFunDone' x (suc n) = inr tt

  doneD-corresp : (x : X) -> fromDelay (doneD x) ≡ delayFunDone x .fst
  doneD-corresp x = funExt (λ { zero → refl ; (suc n) → refl})

  delayFunRunning : (d : PreDelay') -> PreDelay'
  delayFunRunning d = {!!}

  -- runningD-corresp : (d : Delay) -> fromDelay (runningD d)



isSetDelay : ∀ {ℓ : Level} -> {X : Type ℓ} → isSet X → isSet (Delay X)
isSetDelay {X = X} p =
  isSetRetract fromDelay toDelay retr (isSetΠ λ n → isSet⊎ p isSetUnit)
  where open Alternative X