(** An alternate presentation of infinite traces as infinite concatenations of nonempty finite traces. *)
CoInductive traceinf': Type :=
| Econsinf': forall (t: trace) (T: traceinf'), t <> E0 -> traceinf'.
Program Definition split_traceinf' (t: trace) (T: traceinf') (NE: t <> E0): event * traceinf' :=
match t with
| nil => _
| e :: nil => (e, T)
| e :: t' => (e, Econsinf' t' T _)
end.
Next Obligation.
elimtype False. elim NE. auto.
Qed.
Next Obligation.
red; intro. elim (H e). rewrite H0. auto.
Qed.
CoFixpoint traceinf_of_traceinf' (T': traceinf') : traceinf :=
match T' with
| Econsinf' t T'' NOTEMPTY =>
let (e, tl) := split_traceinf' t T'' NOTEMPTY in
Econsinf e (traceinf_of_traceinf' tl)
end.
Remark unroll_traceinf':
forall T, T = match T with Econsinf' t T' NE => Econsinf' t T' NE end.
Remark unroll_traceinf:
forall T, T = match T with Econsinf t T' => Econsinf t T' end.

(* Specifications: *)
Lemma traceinf_traceinf'_app:
forall t T NE,
traceinf_of_traceinf' (Econsinf' t T NE) = t *** traceinf_of_traceinf' T.
Lemma traceinf_traceinf'_app:
forall t T NE,
traceinf_of_traceinf' (Econsinf' t T NE) = t *** traceinf_of_traceinf' T.