(** In order to state our example equality, we define an enumeration stream and a map operation for streams. *)
CoFixpoint map f s : stream :=
match s with cons n s' => cons (f n) (map f s') end.
(** *** A proof using [cofix]  We will now prove, using [cofix], that for any [n] the stream [enumerate n] is equal to the stream [cons n (map S (enumerate n))]. *)
(** First, we define an equality [seq] on streams.  Usually, one would do this as follows.  [CoInductive seq : stream -> stream -> Prop :=] #<br># [  | seq_fold : forall n s1 s2 (R : seq s1 s2), seq (cons n s1) (cons n s2).]  Instead, we define the generating function, [seq_gen], beforehand, and then define [seq] as its greatest fixed point using [CoInductive].  The reason is simply that we need [seq_gen] later when using [paco].  If applying parameterized coinduction to an existing development where the generating function is not explicit, it can always easily be made explicit.  Note that, albeit the use of [Inductive], the definition of [seq_gen] is not recursive. *)
Inductive seq_gen seq : stream -> stream -> Prop :=
| _seq_gen : forall n s1 s2 (R : seq s1 s2 : Prop), seq_gen seq (cons n s1) (cons n s2).
Hint Constructors seq_gen.
CoInductive seq : stream -> stream -> Prop :=
| seq_fold : forall s1 s2, seq_gen seq s1 s2 -> seq s1 s2.
(** Second, we do the actual proof. *)

(* Specifications: *)
Theorem example : forall n, seq (enumerate n) (cons n (map S (enumerate n))).
Definition seq' s1 s2 := paco2 seq_gen bot2 s1 s2.