```------------------------------------------------------------------------
-- This approach appears to be both awkward to use and non-trivial to
-- understand
------------------------------------------------------------------------

module NonDeterministic.LongestPrefix where

open import Data.Nat
open import Data.List
open import Data.Colist hiding ([_]; _⊑_)
open import Coinduction
open import Data.Maybe
open import Data.Product
open import Relation.Nullary
open import Relation.Binary.PropositionalEquality

open import NonDeterministic.Expr

------------------------------------------------------------------------
-- Partial lists

-- A partial list can end in ⊥.

infixr 5 _∷_

data PartialList (A : Set) : Set where
⊥   : PartialList A
[]  : PartialList A
_∷_ : (x : A) (xs : PartialList A) → PartialList A

-- xs ⊑ ys means that xs is an approximation of ys.

infix 4 _⊑_

data _⊑_ {A} : PartialList A → Colist A → Set where
⊥   : ∀ {ys}                          → ⊥      ⊑ ys
[]  :                                   []     ⊑ []
_∷_ : ∀ x {xs ys} (xs⊑ys : xs ⊑ ♭ ys) → x ∷ xs ⊑ x ∷ ys

------------------------------------------------------------------------
-- Semantics

-- []⊑Trace[ e ] means that [] is an approximation of the trace of e.
--
-- The use of coinduction here is unsatisfactory to me. It would
-- perhaps be more natural to use ⊥ as the semantics/trace of a
-- non-terminating, non-productive computation (an infinite sequence
-- of nops which does not emit any messages). In that case I believe
-- that it would be correct to say that ms (a partial stream) is one
-- of the traces of e if
--   ⑴ all /finite/ approximations of ms are approximations of the
--     trace of e, and also
--   ⑵ ms is not an approximation of some other partial stream ms′
--     satisfying ⑴, ignoring streams ms′ that differ from ms just by
--     the addition of trailing external messages.
-- However, the second part of ⑵ (ignoring…) seems a bit ugly, so I
-- have not pursued this definition.

data []⊑Trace[_] : Expr → Set where
nop : ∀ {e} (x : ∞ []⊑Trace[ ♭ e ]) → []⊑Trace[ nop e ]

-- ms ⊑Trace[ e ] means that ms is an approximation of the trace of e.

infix 4 _⊑Trace[_]

data _⊑Trace[_] : PartialList Msg → Expr → Set where
⊥    : ∀ {e}                             → ⊥           ⊑Trace[        e ]
[]   : ∀ {e}      (x :  []⊑Trace[   e ]) → []          ⊑Trace[        e ]
nop  : ∀ {e ms}   (x : ms ⊑Trace[ ♭ e ]) → ms          ⊑Trace[ nop    e ]
tick : ∀ {e m ms} (x : ms ⊑Trace[ ♭ e ]) → user m ∷ ms ⊑Trace[ tick m e ]
tock : ∀ {e m ms} (x : ms ⊑Trace[   e ]) → ext  m ∷ ms ⊑Trace[        e ]

-- A colist of messages is a trace of e if all its approximations are
-- approximations of /some/ trace of e.

infix 4 _HasTrace_

_HasTrace_ : Semantics
e HasTrace ms = ∀ {p} → p ⊑ ms → p ⊑Trace[ e ]

------------------------------------------------------------------------
-- Examples

[]⊑Trace[nops] : []⊑Trace[ nops ]
[]⊑Trace[nops] = nop (♯ []⊑Trace[nops])

possible : nops HasTrace []
possible ⊥  = ⊥
possible [] = [] []⊑Trace[nops]

no-msgs : ∀ {m p} → ¬ user m ∷ p ⊑Trace[ nops ]
no-msgs (nop x) = no-msgs x

impossible : ∀ {m ms} → ¬ nops HasTrace (user m ∷ ms)
impossible {m} ht = no-msgs (ht (user m ∷ ⊥))

ok : ticks HasTrace scissors
ok ⊥                   = ⊥
ok (.(user ✂) ∷ xs⊑ys) = tick (ok xs⊑ys)
```