ITree.Interp.Traces
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.
Lemma is_traceF_tau : forall {E R} (t : itree E R) tr,
is_traceF (observe t) tr <->
is_traceF (TauF t) tr.
Proof.
intros. split; intros.
- constructor. remember (observe t).
generalize dependent t.
induction H; intros; subst; constructor; eapply IHis_traceF; auto.
- inversion H; subst; try constructor; auto.
Qed.
Lemma sutt_trace_incl : forall {E R} (t1 t2 : itree E R),
sutt eq t1 t2 -> trace_incl t1 t2.
Proof.
red. intros. red in H0. remember (observe t1).
generalize dependent t1. generalize dependent t2.
induction H0; intros; try solve [constructor].
- punfold H. rewrite <- Heqi in H.
remember (RetF _). remember (observe t2).
generalize dependent t2.
induction H; intros; try inv Heqi0; red; rewrite <- Heqi1; constructor.
eapply IHsuttF; eauto.
- apply IHis_traceF with (t1:=t); auto.
apply sutt_inv_tau_left. red. red in H. rewrite <- Heqi in H. auto.
- punfold H. rewrite <- Heqi in H.
remember (VisF _ _). remember (observe t2).
generalize dependent t2.
induction H; intros; try discriminate.
+ inv_Vis. subst. red. rewrite <- Heqi1. constructor.
+ red. rewrite <- Heqi1. constructor. eapply IHsuttF; eauto.
- punfold H. rewrite <- Heqi in H.
remember (VisF _ _). remember (observe t2).
generalize dependent t2.
induction H; intros; try discriminate.
+ inv_Vis. pclearbot. subst. red. rewrite <- Heqi1. constructor.
eapply IHis_traceF; auto.
+ red. rewrite <- Heqi1. constructor. apply IHsuttF; auto.
Qed.
Lemma eutt_trace_eq : forall {E R} (t1 t2 : itree E R),
t1 ≈ t2 -> trace_eq t1 t2.
Proof.
split.
- apply sutt_trace_incl; apply eutt_sutt; auto.
- symmetry in H. apply sutt_trace_incl; apply eutt_sutt; auto.
Qed.
Lemma eq_trace_inv {E R} (t1 t2 : @trace E R) (H : t1 = t2)
: match t1, t2 with
| TEnd, TEnd => True
| TRet r1, TRet r2 => r1 = r2
| TEventEnd e1, TEventEnd e2 => exists p, eqeq E p e1 e2
| TEventResponse e1 x1 t1, TEventResponse e2 x2 t2 =>
exists p, eqeq E p e1 e2 /\ eqeq (fun X => X) p x1 x2 /\ t1 = t2
| _, _ => False
end.
Proof.
destruct H, t1; auto.
- exists eq_refl; cbn; auto.
- exists eq_refl; cbn; auto.
Qed.
Lemma trace_incl_sutt : forall {E R} (t1 t2 : itree E R),
trace_incl t1 t2 -> sutt eq t1 t2.
Proof.
intros E R. pcofix CIH. pstep. intros t1 t2 Hincl.
unfold trace_incl in *. unfold is_trace in *.
destruct (observe t1).
- assert (H : is_traceF (RetF r0 : itreeF E R (itree E R)) (TRet r0)) by constructor.
apply Hincl in H. clear Hincl. destruct (observe t2); inv H.
+ constructor. auto.
+ constructor.
remember (observe t). remember (TRet _).
generalize dependent t.
induction H1; intros; try inv Heqt0; auto.
constructor. eapply IHis_traceF; eauto.
- constructor. right. apply CIH. intros. apply Hincl. constructor. auto.
- assert (H: is_traceF (VisF e k) (TEventEnd e)) by constructor.
apply Hincl in H. destruct (observe t2); inv H.
+ constructor.
assert (forall tr, is_traceF (VisF e k) tr -> is_traceF (observe t) tr).
{
intros. rewrite is_traceF_tau. apply Hincl; auto.
}
clear Hincl. rename H into Hincl.
remember (observe t). remember (TEventEnd _).
generalize dependent t.
induction H1; intros; try discriminate.
* constructor. eapply IHis_traceF; eauto.
intros. rewrite is_traceF_tau. apply Hincl; auto.
* apply eq_trace_inv in Heqt0; destruct Heqt0 as [<- <-].
subst. constructor. intro. right. apply CIH. intros.
assert (is_traceF (VisF e k) (TEventResponse e x tr)) by (constructor; auto).
apply Hincl in H1. inv H1.
apply inj_pair2 in H5; apply inj_pair2 in H7; subst; auto.
+ apply inj_pair2 in H2; apply inj_pair2 in H5. subst. constructor. intro. right. apply CIH. intros.
assert (is_traceF (VisF e k) (TEventResponse e x tr)) by (constructor; auto).
apply Hincl in H0. inv H0. apply inj_pair2 in H5; apply inj_pair2 in H7. subst. auto.
Qed.
Theorem trace_incl_iff_sutt : forall {E R} (t1 t2 : itree E R),
sutt eq t1 t2 <-> trace_incl t1 t2.
Proof.
split.
- apply sutt_trace_incl.
- apply trace_incl_sutt.
Qed.
Lemma trace_eq_eutt : forall {E R} (t1 t2 : itree E R),
trace_eq t1 t2 -> t1 ≈ t2.
Proof.
intros E R t1 t2 [? ?]. apply sutt_eutt.
- apply trace_incl_sutt; auto.
- apply trace_incl_sutt in H0. clear H.
generalize dependent t1. generalize dependent t2. pcofix CIH; pstep; intros.
punfold H0. induction H0; constructor; try red; pclearbot; eauto with paco.
right. rewrite itree_eta'. eauto with paco.
Qed.
Theorem trace_eq_iff_eutt : forall {E R} (t1 t2 : itree E R),
t1 ≈ t2 <-> trace_eq t1 t2.
Proof.
split.
- apply eutt_trace_eq.
- apply trace_eq_eutt.
Qed.
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.
Proof.
Abort.
(* Set-of-traces monad *)
Definition traces (E : Type -> Type) (R : Type) : Type :=
@trace E R -> Prop.
Definition bind_traces {E : Type -> Type} {R S : Type}
(ts : traces E R) (kts : R -> traces E S) : traces E S :=
fun tr =>
(tr = TEnd /\ ts TEnd) \/
(exists X (e : E X), tr = TEventEnd e /\ ts (TEventEnd e)) \/
(exists r tr1 tr2,
tr = app_trace tr1 tr2 /\
trace_ret tr1 = Some r /\
ts tr1 /\
kts r tr).
Definition ret_traces {E : Type -> Type} {R : Type} :
R -> traces E R :=
fun r tr =>
tr = TEnd \/ tr = TRet r.