Alectryon normally produces plain HTML files. For very large proofs, these files can get quite large (sometimes hundreds of megabytes), but they also tend to be highly redundant; hence, Alectryon also has the ability to generate “minified” HTML files, which contain special pointers (“backreferences”) to previous parts of the document. These backreferences are resolved dynamically when the page is displayed in a web browser.
Here is an example proof, written in a way that generates lots of redundant objects (for example, section variables appear in the proof context at every step of the proof):
Require Import List. Import ListNotations. Section Folds. Context {A} (op: A -> A -> A) (init: A). Context (init_comm: forall a, op init a = op a init). Context (op_assoc: forall x y z, op (op x y) z = op x (op y z)).
Step 1: prove that init can be moved around:
A:Typeop:A -> A -> Ainit:Ainit_comm:forall a : A, op init a = op a initop_assoc:forall x y z : A, op (op x y) z = op x (op y z)l:list Aforall a : A, fold_left op l (op init a) = op a (fold_left op l init)256789forall a : A, fold_left op [] (op init a) = op a (fold_left op [] init)56789a:AaIHl:forall a : A, fold_left op l (op init a) = op a (fold_left op l init)forall a0 : A, fold_left op (a :: l) (op init a0) = op a0 (fold_left op (a :: l) init)10forall a : A, op init a = op a init14forall a0 : A, fold_left op l (op (op init a0) a) = op a0 (fold_left op l (op init a))5678915op init a = op a init5678915a16a0:Afold_left op l (op (op init a0) a) = op a0 (fold_left op l (op init a))eauto using init_comm.21262826fold_left op l (op init (op a0 a)) = op a0 (fold_left op l (op init a))26op (op a0 a) (fold_left op l init) = op a0 (fold_left op l (op init a))26op a0 (op a (fold_left op l init)) = op a0 (fold_left op l (op init a))reflexivity. Qed.26op a0 (fold_left op l (op init a)) = op a0 (fold_left op l (op init a))
Step 2: prove that fold_left and fold_right are equivalent.
10forall l : list A, fold_left op l init = fold_right op init l3f4fold_left op l init = fold_right op init l56789al':=l:list A4656789l':=[]:list Afold_left op [] init = fold_right op init []5678915al':=a :: l:list AIHl:let l' := l in fold_left op l init = fold_right op init lfold_left op (a :: l) init = fold_right op init (a :: l)4finit = init54fold_left op l (op init a) = op a (fold_right op init l)59reflexivity.5a545e54fold_left op l (op init a) = op a (fold_left op l init)reflexivity. Qed. End Folds.54op a (fold_left op l init) = op a (fold_left op l init)