An example using Coqdoc
- 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 on every sentence, for example.
Here's an *inductive specification* of evenness:
Inductive Even : nat -> Prop :=
| EvenO : Even O
| EvenS : forall n, Even n -> Even (S (S n)).
… and a corresponding decision procedure:
Fixpoint even (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?
forall n : nat, even n = true <-> Even nforall n : nat, even n = true <-> Even neven 0 = true <-> Even 0n:natIHn:even n = true <-> Even neven (S n) = true <-> Even (S n)true = true <-> Even 0n:natIHn:even n = true <-> Even neven (S n) = true <-> Even (S n)true = true <-> Even 0all: constructor.true = true -> Even 0Even 0 -> true = truen:natIHn:even n = true <-> Even neven (S n) = true <-> Even (S n)
The induction hypothesis doesn't apply — maybe we need to destruct ``n``?
IHn:even 0 = true <-> Even 0even 1 = true <-> Even 1n:natIHn:even (S n) = true <-> Even (S n)even (S (S n)) = true <-> Even (S (S n))split; inversion 1.IHn:even 0 = true <-> Even 0even 1 = true <-> Even 1n:natIHn:even (S n) = true <-> Even (S n)even (S (S n)) = true <-> Even (S (S n))
Stuck again!
Abort.
The usual approach is to strengthen the spec:
forall n : nat, (even n = true <-> Even n) /\ (even (S n) = true <-> Even (S n))forall n : nat, (even n = true <-> Even n) /\ (even (S n) = true <-> Even (S n))(true = true <-> Even 0) /\ (false = true <-> Even 1)n:natIHn:(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 0false = true -> Even 1Even 1 -> false = trueall: inversion 1.false = true -> Even 1Even 1 -> false = truen:natIHn:(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:natHne:even n = true -> Even nHnE:Even n -> even n = trueHSne: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:natHne:even n = true -> Even nHnE:Even n -> even n = trueHSne:even (S n) = true -> Even (S n)HSnE:Even (S n) -> even (S n) = trueeven (S n) = true -> Even (S n)n:natHne:even n = true -> Even nHnE:Even n -> even n = trueHSne:even (S n) = true -> Even (S n)HSnE:Even (S n) -> even (S n) = trueEven (S n) -> even (S n) = truen:natHne:even n = true -> Even nHnE:Even n -> even n = trueHSne:even (S n) = true -> Even (S n)HSnE:Even (S n) -> even (S n) = trueeven n = true -> Even (S (S n))n:natHne:even n = true -> Even nHnE:Even n -> even n = trueHSne:even (S n) = true -> Even (S n)HSnE:Even (S n) -> even (S n) = trueEven (S (S n)) -> even n = trueinversion 1; eauto. Qed.n:natHne:even n = true -> Even nHnE:Even n -> even n = trueHSne:even (S n) = true -> Even (S n)HSnE:Even (S n) -> even (S n) = trueEven (S (S n)) -> even n = true
even_Even_fp:forall n : nat, even n = true <-> Even nn:nateven n = true <-> Even neven_Even_fp:forall n : nat, even n = true <-> Even nn:nateven n = true <-> Even neven_Even_fp:forall n : nat, even n = true <-> Even ntrue = true <-> Even 0even_Even_fp:forall n : nat, even n = true <-> Even nfalse = true <-> Even 1even_Even_fp:forall n : nat, even n = true <-> Even nn:nateven n = true <-> Even (S (S n))repeat constructor.even_Even_fp:forall n : nat, even n = true <-> Even ntrue = true <-> Even 0split; inversion 1.even_Even_fp:forall n : nat, even n = true <-> Even nfalse = true <-> Even 1even_Even_fp:forall n : nat, even n = true <-> Even nn:nateven n = true <-> Even (S (S n))even_Even_fp:forall n : nat, even n = true <-> Even nn:nateven n = true -> Even (S (S n))even_Even_fp:forall n : nat, even n = true <-> Even nn:natEven (S (S n)) -> even n = trueconstructor; apply even_Even; assumption.even_Even_fp:forall n : nat, even n = true <-> Even nn:nateven n = true -> Even (S (S n))inversion 1; apply even_Even; assumption. Qed.even_Even_fp:forall n : nat, even n = true <-> Even nn:natEven (S (S n)) -> even n = true