Built with Alectryon, running Coq+SerAPI. Bubbles () indicate interactive fragments: hover for details, tap to reveal contents. Use Ctrl+↑Ctrl+↓ to navigate, Ctrl+🖱️ to focus. On Mac, use ⌘ instead of Ctrl.
(** * An example using Coqdoc This is a hybrid rendering mode: coqdoc is used to render literate comments, and Alectryon is used to render code, responses, and goals. It's a bit as if coqdoc was just a markup language, _without anything specific to Coq_. Cons: - There's a dependency on [coqdoc] - It doesn't use a standard markup language like reST, markdown, etc. - You can't switch back and forth between a code view and a prose view: all prose editing happens in comments. - Annotations can't be applied to whole blocks, so if you want to unfold all sentences in a block you have to say (* .unfold *) on every sentence, for example. **)(** ** Some code **)(**Here's an *inductive specification* of evenness:**)InductiveEven : nat -> Prop :=
| EvenO : Even O
| EvenS : foralln, Even n -> Even (S (S n)).(**… and a corresponding decision procedure:**)Fixpointeven (n: nat): bool :=
match n with
| 0 => true
| 1 => false
| S (S n) => even n
end.(* Ensure that we never unfold [even (S n)] *)Arguments even : simpl nomatch.(**Can we prove it correct?**)
foralln : nat, even n = true <-> Even n
foralln : nat, even n = true <-> Even n
even 0 = true <-> Even 0
n:nat
IHn:even n = true <-> Even n
even (S n) = true <-> Even (S n)
true = true <-> Even 0
n:nat
IHn:even n = true <-> Even n
even (S n) = true <-> Even (S n)
true = true <-> Even 0
true = true -> Even 0
Even 0 -> true = true
all: constructor.
n:nat
IHn:even n = true <-> Even n
even (S n) = true <-> Even (S n)
In environment
n : nat
IHn : even n = true <-> Even n
H : even n = true -> Even n
Unable to unify"Even n"with"even (S n) = true <-> Even (S n)".
(**The induction hypothesis doesn't apply — maybe we need to destruct ``n``?**)
IHn:even 0 = true <-> Even 0
even 1 = true <-> Even 1
n:nat
IHn:even (S n) = true <-> Even (S n)
even (S (S n)) = true <-> Even (S (S n))
IHn:even 0 = true <-> Even 0
even 1 = true <-> Even 1
split; inversion1.
n:nat
IHn:even (S n) = true <-> Even (S n)
even (S (S n)) = true <-> Even (S (S n))
(**Stuck again!**)Abort.(** ** Strengthening the spec **)(** The usual approach is to strengthen the spec: **)
foralln : nat,
(even n = true <-> Even n) /\
(even (S n) = true <-> Even (S n))
foralln : nat,
(even n = true <-> Even n) /\
(even (S n) = true <-> Even (S n))
(true = true <-> Even 0) /\ (false = true <-> Even 1)
n:nat
IHn:(even n = true <-> Even n) /\ (even (S n) = true <-> Even (S n))
(even (S n) = true <-> Even (S n)) /\
(even n = true <-> Even (S (S n)))
(true = true <-> Even 0) /\ (false = true <-> Even 1)
true = true -> Even 0
false = true -> Even 1
Even 1 -> false = true
false = true -> Even 1
Even 1 -> false = true
all: inversion1.
n:nat
IHn:(even n = true <-> Even n) /\ (even (S n) = true <-> Even (S n))
(even (S n) = true <-> Even (S n)) /\
(even n = true <-> Even (S (S n)))
n:nat
Hne:even n = true -> Even n
HnE:Even n -> even n = true
HSne:even (S n) = true -> Even (S n)
HSnE:Even (S n) -> even (S n) = true
(even (S n) = true <-> Even (S n)) /\
(even n = true <-> Even (S (S n)))
n:nat
Hne:even n = true -> Even n
HnE:Even n -> even n = true
HSne:even (S n) = true -> Even (S n)
HSnE:Even (S n) -> even (S n) = true
even (S n) = true -> Even (S n)
n:nat
Hne:even n = true -> Even n
HnE:Even n -> even n = true
HSne:even (S n) = true -> Even (S n)
HSnE:Even (S n) -> even (S n) = true
Even (S n) -> even (S n) = true
n:nat
Hne:even n = true -> Even n
HnE:Even n -> even n = true
HSne:even (S n) = true -> Even (S n)
HSnE:Even (S n) -> even (S n) = true
even n = true -> Even (S (S n))
n:nat
Hne:even n = true -> Even n
HnE:Even n -> even n = true
HSne:even (S n) = true -> Even (S n)
HSnE:Even (S n) -> even (S n) = true
Even (S (S n)) -> even n = true
n:nat
Hne:even n = true -> Even n
HnE:Even n -> even n = true
HSne:even (S n) = true -> Even (S n)
HSnE:Even (S n) -> even (S n) = true
Even (S (S n)) -> even n = true
inversion1; eauto.Qed.(** ** Writing a fixpointBut writing a fixpoint is much nicer: **)
even_Even_fp:foralln : nat,
even n = true <-> Even n
n:nat
even n = true <-> Even n
even_Even_fp:foralln : nat,
even n = true <-> Even n
n:nat
even n = true <-> Even n
even_Even_fp:foralln : nat,
even n = true <-> Even n
true = true <-> Even 0
even_Even_fp:foralln : nat,
even n = true <-> Even n
false = true <-> Even 1
even_Even_fp:foralln : nat,
even n = true <-> Even n
n:nat
even n = true <-> Even (S (S n))
even_Even_fp:foralln : nat,
even n = true <-> Even n
true = true <-> Even 0
repeatconstructor.
even_Even_fp:foralln : nat,
even n = true <-> Even n
false = true <-> Even 1
split; inversion1.
even_Even_fp:foralln : nat,
even n = true <-> Even n
n:nat
even n = true <-> Even (S (S n))
even_Even_fp:foralln : nat,
even n = true <-> Even n
n:nat
even n = true -> Even (S (S n))
even_Even_fp:foralln : nat,
even n = true <-> Even n
n:nat
Even (S (S n)) -> even n = true
even_Even_fp:foralln : nat,
even n = true <-> Even n
n:nat
even n = true -> Even (S (S n))
constructor; apply even_Even; assumption.
even_Even_fp:foralln : nat,
even n = true <-> Even n