(** * Equivalence up to taus *)
(** Abbreviated as [eutt]. *)
(** We consider [Tau] as an "internal step", that should not be visible to the outside world, so adding or removing [Tau] constructors from an itree should produce an equivalent itree.  We must be careful because there may be infinite sequences of taus (i.e., [spin]). Here we shall only allow inserting finitely many [Tau]s between any two visible steps ([Ret] or [Vis]), so that [spin] is only related to itself. This ensures that equivalence up to taus is transitive (and in fact an equivalence relation). *)
(** A rewrite hint database named [itree] is available via the tactic [autorewrite with itree] as a custom simplifier of expressions using mainly [Ret], [Tau], [Vis], [ITree.bind] and [ITree.Interp.Interp.interp]. *)
(** This file contains only the definition of the [eutt] relation. Theorems about [eutt] are split in two more modules:  - [ITree.Eq.UpToTausCore] proves that [eutt] is reflexive, symmetric, and that [ITree.Eq.Eq.eq_itree] is a subrelation of [eutt]. Equations for [ITree.Core.ITreeDefinition] combinators which only rely on those properties can also be found here.  - [ITree.Eq.UpToTausEquivalence] proves that [eutt] is transitive, and, more generally, contains theorems for up-to reasoning in coinductive proofs. *)
(** Splitting things this way makes the library easier to build in parallel. *)
(* begin hide *)
Core.ITreeDefinition
Eq.Eq.
Local Open Scope itree.
(* end hide *)
(**** START: taken from Paco-4.0.1 ****)

Lemma gpaco2_gpaco {T0 T1} gf (gf_mon: @monotone2 T0 T1 gf) clo r rg:
gpaco2 gf clo (gpaco2 gf clo r rg) (gupaco2 gf clo (rg \2/ r)) <2= gpaco2 gf clo r rg.