(** * 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.(** * 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.

(* Specifications: *)
Lemma sunf_eq : forall s, s = sunf s.