Skip to content

The Tally project

Tally is the small Rocq project behind every example here. It lives in docs/site/example, compiled with Rocq 9.1.0. Its .glob files and facts.json are committed, so the site builds without Rocq, and generate.sh recompiles it.

File Module On the site
theories/Core.v Tally.Core Page
theories/Laws.v Tally.Laws Page
theories/Prose.v Tally.Prose Page

_CoqProject

-Q theories Tally

theories/Core.v
theories/Laws.v
theories/Prose.v

Core.v

(**md # Core

A tally is a list of counts. This module defines the type and the two functions the rest of the
project reasons about: [`total`](Core.html#total) and [`append`](Core.html#append).
*)

(** A list of counts. *)
Inductive tally : Type :=
  | empty : tally
  | cons : nat -> tally -> tally.

Declare Scope tally_scope.
Delimit Scope tally_scope with tally.
Infix "::" := cons (at level 60, right associativity) : tally_scope.
Open Scope tally_scope.

(** The sum of every count in a tally.
    - [t:] the tally summed. *)
Fixpoint total (t : tally) : nat :=
  match t with
  | empty => 0
  | n :: rest => n + total rest
  end.

(**md The counts of `a`, followed by the counts of `b`.

- [a:] the counts that come first.
- [b:] the counts that come last. *)
Fixpoint append (a b : tally) : tally :=
  match a with
  | empty => b
  | n :: rest => n :: append rest b
  end.

(** How many counts a tally holds.
    - [t:] the tally measured. *)
Fixpoint size (t : tally) : nat :=
  match t with
  | empty => 0
  | _ :: rest => S (size rest)
  end.

Laws.v

From Tally Require Import Core.

(**md # Laws

What [`total`](Core.html#total), [`append`](Core.html#append) and [`size`](Core.html#size)
guarantee. Theorems whose comment opens with a bold line appear on the Guarantees page.
*)

Open Scope tally_scope.

(**md ## Arithmetic *)

(** Addition regroups. *)
Lemma add_regroup (a b c : nat) : a + b + c = a + (b + c).
Proof.
  induction a as [| a IH].
  - reflexivity.
  - simpl. rewrite IH. reflexivity.
Qed.

(**md ## Appending *)

(**md
**Appending adds totals.**

The total of two tallies appended equals the sum of their totals.

- [a:] the counts that come first.
- [b:] the counts that come last.
*)
Theorem total_append (a b : tally) : total (append a b) = total a + total b.
Proof.
  induction a as [| n rest IH].
  - reflexivity.
  - simpl. rewrite IH. symmetry. apply add_regroup.
Qed.

(**md
**The empty tally changes nothing.**

Appending `empty` leaves the total as it was.
*)
Corollary total_append_empty (a : tally) : total (append a empty) = total a + 0.
Proof.
  apply total_append.
Qed.

(**md ## Assumed and unfinished *)

(** An assumption, which the badge on any theorem using it reports. *)
Axiom counts_are_small : forall t : tally, size t = size t.

(**md
**Size is stable.**

Rests on the assumption above, so its badge reads as axiom-dependent.
*)
Theorem size_stable (t : tally) : size t = size t.
Proof.
  exact (counts_are_small t).
Qed.

(**md
**Appending adds sizes.**

Not proved yet, so it sits in the Open group.
*)
Theorem size_append (a b : tally) : size (append a b) = size a + size b.
Admitted.

(**md
**The claim that all totals match is false.**

The name's `_falsified` suffix files this disproof in the Falsified group.
*)
Theorem totals_differ_falsified : total (1 :: empty) <> total (2 :: empty).
Proof.
  discriminate.
Qed.

(**md
**Generated tallies sum correctly.**

@checked with one thousand generated tallies, which files it in the Checks group.
*)
Theorem generated_sum : total (1 :: 2 :: empty) = 3.
Proof.
  reflexivity.
Qed.

Prose.v

From Tally Require Import Core.

(**md # Prose syntax

Every comment form the navigator reads. The documentation site quotes these comments and renders
them with the plugin's own code.
*)

(** * A doc comment heading

    One to four stars open a heading in a doc comment. *)

(** ** A second-level heading *)

(** A paragraph in a doc comment.
    Lines join into one paragraph, and a blank line starts the next.

    Square brackets mark code: [total] links to its declaration, and [1 + 1] stays plain code. *)
Definition doc_paragraphs := total empty.

(** - This dash is plain text, since doc comments have no lists: only headings, paragraphs and
    [code]. Use a Markdown comment for lists. *)
Definition doc_no_lists := 0.

(**md ## A Markdown heading

The `md` marker after the opening stars selects Markdown, with one to six `#` marks for a heading. *)

(**md **Bold**, *emphasis*, `total` as a linked name and `1 + 1` as plain code.

- A list item
- Another, with a [link to a declaration](Core.html#append)

| Form | Marker | Lists |
|---|---|---|
| Doc | none | no |
| Markdown | `md` | yes |

```text
A fenced block. `total` stays text here.
```

An external [link](https://rocq-prover.org), and raw HTML shown as text: <b>not bold</b>. *)
Definition markdown_forms := total empty.

(** Arguments in a doc comment.
    - [n:] the count added, whose entry
      continues on an indented line.
    - [t:] the tally extended, mentioning [size]. *)
Definition push (n : nat) (t : tally) : tally := cons n t.

(**md Arguments in a Markdown comment.

- [t:] the tally read, mentioning `append`. *)
Definition is_empty (t : tally) : bool :=
  match t with
  | empty => true
  | cons _ _ => false
  end.

(* A plain comment above a declaration documents it, as a doc comment does. *)
Definition with_plain_comment (* a comment inside the statement *) := 0.

(** A comment that has a line of its own, and is attached to no declaration, reads as prose between
    the declarations. *)

(**md
**A first line wholly in bold titles a theorem.**

A `Theorem` or `Corollary` with this form appears on the Guarantees page under that title. A `Lemma`
never does.
*)
Theorem titled_theorem : total empty = 0.
Proof.
  (* A plain comment inside a proof folds with the proof. *)
  reflexivity.
Qed.