(** ** Example: mutual coinduction

    The third and last example shows that [paco] also works for mutual
    coinduction.  Here, the mutuality involves two predicates.
*)(* *)


(** We define two generating functions (using the [inftree] type from
    before).
*)

Inductive eqone_gen eqone eqtwo : inftree -> Prop :=
  | _eqone_gen : forall tl tr (EQL : eqone tl : Prop) (EQR : eqtwo tr : Prop),
                    eqone_gen eqone eqtwo (node 1 tl tr).(** ** Example: mutual coinduction

    The third and last example shows that [paco] also works for mutual
    coinduction.  Here, the mutuality involves two predicates.
*)(* *)


(** We define two generating functions (using the [inftree] type from
    before).
*)

Inductive eqone_gen eqone eqtwo : inftree -> Prop :=
  | _eqone_gen : forall tl tr (EQL : eqone tl : Prop) (EQR : eqtwo tr : Prop),
                    eqone_gen eqone eqtwo (node 1 tl tr).Inductive eqtwo_gen eqone eqtwo : inftree -> Prop :=
  | _eqtwo_gen : forall tl tr (EQL : eqone tl : Prop) (EQR : eqtwo tr : Prop),
                   eqtwo_gen eqone eqtwo (node 2 tl tr).Inductive eqtwo_gen eqone eqtwo : inftree -> Prop :=
  | _eqtwo_gen : forall tl tr (EQL : eqone tl : Prop) (EQR : eqtwo tr : Prop),
                   eqtwo_gen eqone eqtwo (node 2 tl tr).(** *** A proof via [cofix]

    Using these, we now define two mutually coinductive predicates
    [eqone] and [eqtwo].  It is easy to see intuitively that they
    contain all trees that are equal to [one] and [two] from above,
    respectively.  We then prove that [eqone] contains [eins].
*)

CoInductive eqone (t : inftree) : Prop :=
  | eqone_fold (EQ : eqone_gen eqone eqtwo t)
with eqtwo (t : inftree) : Prop :=
  | eqtwo_fold (EQ : eqtwo_gen eqone eqtwo t).(** *** A proof via [cofix]

    Using these, we now define two mutually coinductive predicates
    [eqone] and [eqtwo].  It is easy to see intuitively that they
    contain all trees that are equal to [one] and [two] from above,
    respectively.  We then prove that [eqone] contains [eins].
*)

CoInductive eqone (t : inftree) : Prop :=
  | eqone_fold (EQ : eqone_gen eqone eqtwo t)
with eqtwo (t : inftree) : Prop :=
  | eqtwo_fold (EQ : eqtwo_gen eqone eqtwo t).(** *** A proof via [cofix]

    Using these, we now define two mutually coinductive predicates
    [eqone] and [eqtwo].  It is easy to see intuitively that they
    contain all trees that are equal to [one] and [two] from above,
    respectively.  We then prove that [eqone] contains [eins].
*)

CoInductive eqone (t : inftree) : Prop :=
  | eqone_fold (EQ : eqone_gen eqone eqtwo t)
with eqtwo (t : inftree) : Prop :=
  | eqtwo_fold (EQ : eqtwo_gen eqone eqtwo t).(** *** A proof via [cofix]

    Using these, we now define two mutually coinductive predicates
    [eqone] and [eqtwo].  It is easy to see intuitively that they
    contain all trees that are equal to [one] and [two] from above,
    respectively.  We then prove that [eqone] contains [eins].
*)

CoInductive eqone (t : inftree) : Prop :=
  | eqone_fold (EQ : eqone_gen eqone eqtwo t)
with eqtwo (t : inftree) : Prop :=
  | eqtwo_fold (EQ : eqtwo_gen eqone eqtwo t).

(* Specifications: *)
Lemma eqone_eins : eqone eins.