(** _Note_: One might want to eliminate the use of [pattern] in the
    proof script by replacing the corresponding line with the
    following:

    [rewrite sunf_eq at 1; simpl.]

    However, doing so will result in an invalid proof (rejected at
    [Qed]-time).  The reason is that the proof term created by
    [rewrite] ... [at 1] involves some lemmas from the [Setoid]
    library.  Like most lemmas, these are opaque, so guardedness
    checking cannot inspect their proofs and thus fails.  This is a
    great example of two of the previously mentioned problems with the
    [cofix] approach, namely lack of compositionality and poor
    interaction with standard tactics.
*)(* *)



(** *** A proof using our [pcofix]

    We will now do the same proof, but using the [paco] library.  We
    first simply show the new (but equivalent) definition of stream
    equality and the new proof of the example, and then explain what
    is going on behind the scenes.  In both, we use [paco] constructs
    with suffix "2" because we are dealing with predicates of arity 2
    here.

    _Note_: [Paco] supports predicates of arity up to 8.  Also, it
    supports up to three mutually coinductive predicates (see the last
    example of this tutorial).  In either case, extending this is just
    a matter of copy and paste.

    We also have to prove monotonicity of the generating function
    [seq_gen], which can be discharged by the tactic [pmonauto], and
    register it in the Hint databse [paco].

    _Remark_: Unlike [CoInductive], [paco] does not care whether the
    generating function is given in a _strictly positive_ syntactic
    form; all that matters is that the function is monotone. More
    specifically, [paco2 f] is well defined for an arbitrary generating
    function [f] regardless of whether it is monotone or not. However,
    in order to ensure that [paco2 f bot2] is the greatest fixed point
    of [f], we need monotonicity of [f].
*)

Definition seq' s1 s2 := paco2 seq_gen bot2 s1 s2.

(* Specifications: *)
Lemma seq_gen_mon: monotone2 seq_gen.
Theorem example' : forall n, seq' (enumerate n) (cons n (map S (enumerate n))).
Theorem seq_cons : forall n1 n2 s1 s2 (SEQ : seq (cons n1 s1) (cons n2 s2)), n1 = n2 /\ seq s1 s2.
Theorem seq'_cons : forall n1 n2 s1 s2 (SEQ : seq' (cons n1 s1) (cons n2 s2)), n1 = n2 /\ seq' s1 s2.