(** printing \2/ $\cup$ #&cup;# *)
(** printing <2= $\subseteq$ #&sube;# *)
(** printing forall $\forall$ #&forall;# *)
(** printing -> $\rightarrow$ #&rarr;# *)
(** printing /\ $\land$ #&and;# *)
(** * Illustrating the [paco] library  This tutorial shows how to use our [paco] library to reason about coinductive predicates in Coq.  By coinductive predicates we mean objects that one can define using [CoInductive] and whose type ends in [Prop].  The library implements _parameterized coinduction_, as described in our draft paper entitled #<a href=" http://plv.mpi-sws.org/paco/"># _The Power of Parameterization in Coinductive Proof_ #</a>#.  How does parameterized coinduction compare to Coq's existing support for coinductive proofs?  For proofs by _induction_, Coq provides a tactic called [fix], but proofs done directly with [fix] are required to satisfy a _syntactic guardedness_ criterion.  Fortunately, Coq also generates induction _lemmas_ for every inductive definition, which eliminate the need to ever use the low-level [fix] tactic and worry about guardedness.  For proofs by coinduction, Coq provides a tactic [cofix] analogous to [fix], i.e., also based on a syntactic guardedness criterion.  However, Coq does not generate any lemmas for coinductive definitions.  Consequently, to reason about such definitions, the user must use the low-level [cofix] tactic.  Due to its syntactic nature, [cofix] is problematic in several ways (please see the paper linked above for detailed discussion of these points):  - It is non-compositional. - It is inefficient. - It is not user-friendly. - It interacts poorly with builtin automation tactics.   The [paco] library provides a tactic, [pcofix], which can be seen as a replacement for Coq's builtin [cofix] tactic (in the case of predicates) that does not involve any syntactic guardedness criterion and thus avoids all of these problems.  In addition, like Coq's [cofix], [pcofix] provides built-in support for _incremental_ proofs, i.e., proofs in which the coinduction hypothesis is extended gradually as the proof progresses.  We believe this combination of compositionality, incrementality, robustness, and ease of use makes [pcofix] a superior alternative to [cofix] for proofs about coinductive predicates.  The rest of this tutorial illustrates the use of the [paco] library with the help of three examples. *)(* *)
(** ** Example: stream equality  The first example involves streams of natural numbers and an equality thereon.  We prove a particular equality via [cofix], and then explain how that proof can be turned into one via [pcofix]. *)
(** We start by defining a type of streams of natural numbers. *)
CoInductive stream :=
| cons : nat -> stream -> stream.
(** The following, seemingly useless, lemma is a common trick for working with corecursive terms such as our streams.  (It will be used in the example proofs.)  For details, see for instance #<a href="http://adam.chlipala.net/cpdt/html/Coinductive.html">Adam Chlipala's book on Certified Programming with Dependent Types</a>#. *)
Definition sunf s :=
match s with cons n s' => cons n s' end.

Lemma sunf_eq : forall s, s = sunf s.
CoFixpoint enumerate n : stream :=
cons n (enumerate (S n)).