(** * ITrees as sets of traces *)
(* begin hide *)
List.
paco.
Core.ITreeDefinition
Eq.Eq
Eq.UpToTaus
Eq.SimUpToTaus
Eq.Shallow.
Local Open Scope itree.
(* end hide *)
Inductive trace {E : Type -> Type} {R : Type} : Type :=
| TEnd : trace
| TRet : R -> trace
| TEventEnd : forall {X}, E X -> trace
| TEventResponse : forall {X}, E X -> X -> trace -> trace
.
(* Append two traces, ignoring the end of the first trace. *)
Fixpoint app_trace {E R S} (tr1 : @trace E R) (tr2 : @trace E S) : @trace E S :=
match tr1 with
| TEventResponse e x tr => TEventResponse e x (app_trace tr tr2)
| _ => tr2
end.
(* Get the value in the TRet at the end of the trace, if it exists. *)
Fixpoint trace_ret {E R} (tr : @trace E R) : option R :=
match tr with
| TRet r => (Some r)
| TEventResponse _ _ tr => trace_ret tr
| _ => None
end.
Inductive is_traceF {E : Type -> Type} {R : Type} :
itreeF E R (itree E R) -> @trace E R -> Prop :=
| TraceEmpty : forall t, is_traceF t TEnd
| TraceRet : forall r, is_traceF (RetF r) (TRet r)
| TraceTau : forall t tr,
is_traceF (observe t) tr ->
is_traceF (TauF t) tr
| TraceVisEnd : forall X (e : E X) k,
is_traceF (VisF e k) (TEventEnd e)
| TraceVisContinue : forall X (e : E X) (x : X) k tr,
is_traceF (observe (k x)) tr ->
is_traceF (VisF e k) (TEventResponse e x tr)
.
Definition is_trace {E : Type -> Type} {R : Type} (t : itree E R) :=
is_traceF (observe t).
(* t1 ⊑ t2 *)
Definition trace_incl {E : Type -> Type} {R : Type} :
itree E R -> itree E R -> Prop :=
fun t1 t2 =>
forall tr, is_trace t1 tr -> is_trace t2 tr.
(* t1 ≡ t2 *)
Definition trace_eq {E : Type -> Type} {R : Type} :
itree E R -> itree E R -> Prop :=
fun t1 t2 =>
trace_incl t1 t2 /\ trace_incl t2 t1.
Inductive event (E : Type -> Type) : Type :=
| Event : forall {X}, E X -> X -> event E
.
(* [step_ ev t' t] if [t] steps to [t'] (read right to left!) with visible event [ev]. *)
Inductive step_ {E : Type -> Type} {R : Type}
(ev : event E) (t' : itree E R) :
itree E R -> Prop :=
| StepTau : forall t, step_ ev t' t -> step_ ev t' (Tau t)
| StepVis : forall X (e : E X) (x : X) k,
ev = Event _ e x ->
t' = k x ->
step_ ev t' (Vis e k)
.
Definition step {E : Type -> Type} {R : Type}
(ev : event E) (t t' : itree E R) : Prop :=
step_ ev t' t.
CoInductive simulates {E : Type -> Type} {R : Type} :
itree E R -> itree E R -> Prop :=
| SimStep : forall t1 t2,
(forall ev t1',
step ev t1 t1' ->
exists t2', step ev t2 t2' /\ simulates t1' t2') ->
simulates t1 t2.

Theorem simulates_trace_incl {E : Type -> Type} {R : Type} :
forall t1 t2 : itree E R,
simulates t1 t2 -> trace_incl t1 t2.