Appendix: comparing inductive and coinductive defitions
Require Import SfLib.
Inductive natinf :
Type :=
|
Fin:
nat ->
natinf
|
Inf:
natinf.
Definition succ (
x:
natinf) :
natinf :=
match x with
|
Fin a =>
Fin (
S a)
|
Inf =>
Inf
end.
Consider the following two inference rules, intended to define a predicate
even over the type
natinf (natural numbers extended with a point at infinity).
even n
even 0 ------------------
even(succ(succ n))
It is clear that the predicate
even must satisfy the following specification:
Definition even_spec (
even:
natinf ->
Prop) :
Prop :=
forall n,
even n <-> (
n =
Fin 0 \/
exists m,
n =
succ(
succ m) /\
even m).
However, there are several predicates satisfying even_spec.
Definition even_1 (
x:
natinf) :
Prop :=
exists m,
x =
Fin(
m +
m).
Definition even_2 (
x:
natinf) :
Prop :=
x =
Inf \/
even_1 x.
Lemma even_1_satisfies_spec:
even_spec even_1.
Proof.
unfold even_spec,
even_1.
firstorder.
subst n.
destruct x.
left.
auto.
right.
exists (
Fin (
x +
x)).
split.
simpl.
f_equal.
omega.
exists x;
auto.
subst n.
exists 0;
auto.
subst x.
subst n.
simpl.
exists (
S x0).
f_equal.
omega.
Qed.
Lemma even_2_satisfies_spec:
even_spec even_2.
Proof.
unfold even_spec,
even_2.
intros.
generalize (
even_1_satisfies_spec n).
firstorder.
subst n.
right.
exists Inf;
auto.
subst x.
simpl in H2.
auto.
Qed.
When we transcribe the inference rules as a Coq inductive predicate,
what we get is the smallest (least defined) predicate satisfying even_spec.
Inductive even:
natinf ->
Prop :=
|
even_0:
even (
Fin 0)
|
even_succ:
forall n,
even n ->
even (
succ (
succ n)).
Lemma even_satisfies_spec:
even_spec even.
Proof.
unfold even_spec.
intro.
split.
intros.
inversion H.
left;
auto.
right.
exists n0.
auto.
intros [
A | [
m [
B C]]].
subst n.
apply even_0.
subst n.
apply even_succ;
auto.
Qed.
Lemma even_smallest_fixpoint:
forall (
P:
natinf ->
Prop),
even_spec P ->
forall n,
even n ->
P n.
Proof.
unfold even_spec; intros P FIXPOINT.
induction 1.
rewrite FIXPOINT. auto.
rewrite FIXPOINT. right. exists n; auto.
Qed.
Alternatively, we can ask Coq to define a coinductive predicate.
Note that the two constructors have exactly the same types in
even and coeven.
CoInductive coeven:
natinf ->
Prop :=
|
coeven_0:
coeven (
Fin 0)
|
coeven_succ:
forall n,
coeven n ->
coeven (
succ (
succ n)).
coeven satisfies the specification just like even.
Lemma coeven_satisfies_spec:
even_spec coeven.
Proof.
unfold even_spec.
intro.
split.
intros.
inversion H.
left;
auto.
right.
exists n0.
auto.
intros [
A | [
m [
B C]]].
subst n.
apply coeven_0.
subst n.
apply coeven_succ;
auto.
Qed.
However, coeven is a different predicate than even.
Indeed, coeven Inf holds.
Lemma Inf_coeven:
coeven Inf.
Proof.
... while even Inf does not hold.
Lemma Inf_not_even:
~(
even Inf).
Proof.
coeven is actually the greatest (most defined) predicate that satisfies
even_spec.
Lemma coeven_greatest_fixpoint:
forall (
P:
natinf ->
Prop),
even_spec P ->
forall n,
P n ->
coeven n.
Proof.
unfold even_spec;
intros P FIXPOINT.
cofix COINDHYP.
intros.
rewrite FIXPOINT in H.
destruct H as [
A | [
m [
B C]]].
subst n.
apply coeven_0.
subst n.
apply coeven_succ.
apply COINDHYP.
auto.
Qed.