• Stars
    star
    497
  • Rank 88,652 (Top 2 %)
  • Language Coq
  • License
    MIT License
  • Created almost 8 years ago
  • Updated 3 months ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

Tricks you wish the Coq manual told you [maintainer=@tchajed]

Tricks in Coq

CI

Some tips, tricks, and features in Coq that are hard to discover.

If you have a trick you've found useful feel free to submit an issue or pull request!

Ltac

  • The pattern tactic generalizes an expression over a variable. For example, pattern y transforms a goal of P x y z into (fun y => P x y z) y. An especially useful way to use this is to pattern match on eval pattern y in constr:(P x y z) to extract just the function.
  • lazymatch is like match but without backtracking on failures inside the match action. If you're not using failures for backtracking (this is often the case), then lazymatch gets better error messages because an error inside the action becomes the overall error message rather than the uninformative "no match" error message. (The semantics of match mean Coq can't do obviously do better - it can't distinguish between a bug in the action and intentionally using the failure to prevent pattern matching.)
  • deex (see Deex.v) is a useful tactic for extracting the witness from an exists hypothesis while preserving the name of the witness and hypothesis.
  • Ltac t ::= foo. re-defines the tactic t to foo. This changes the binding, so tactics that refer to t will use the new definition. You can use this for a form of extensibility: write Ltac hook := fail and then use
    repeat match goal with
           | (* initial cases *)
           | _ => hook
           | (* other cases *)
           end
    
    in your tactic. Now the user can insert an extra case in your tactic's core loop by overriding hook.
  • learn approach - see Learn.v for a self-contained example or Clément's thesis for more details
  • unshelve tactical, especially useful with an eapply - good example use case is constructing an object by refinement where the obligations end up being your proofs with the values as evars, when you wanted to construct the values by proof
  • unfold "+" works
  • destruct matches tactic; see coq-tactical's SimplMatch.v
  • using instantiate to modify evar environment (thanks to Jonathan Leivent on coq-club)
  • eexists ?[x] lets one name an existential variable to be able to refer to it later
  • strong induction is in the standard library: Require Import Arith. and use induction n as [n IHn] using lt_wf_ind.
  • induction on the length of a list: Require Import Coq.Arith.Wf_nat. and induction xs as [xs IHxs] using (induction_ltof1 _ (@length _)); unfold ltof in IHxs.
  • debug auto, debug eauto, and debug trivial give traces, including failed invocations. info_auto, info_eauto, and info_trivial are less verbose ways to debug which only report what the resulting proof includes
  • constructor and econstructor backtrack over the constructors over an inductive, which lets you do fun things exploring the constructors of an inductive type. See Constructors.v for some demonstrations.
  • There's a way to destruct and maintain an equality: destruct_with_eqn x. You can also do destruct x eqn:H to explicitly name the equality hypothesis. This is similar to case_eq x; intros; I'm not sure what the practical differences are.
  • rew H in t notation to use eq_rect for a (safe) "type cast". Need to import EqNotations - see RewNotation.v for a working example.
  • intro-patterns can be combined in a non-trivial way: intros [=->%lemma] -- see IntroPatterns.v.
  • change tactic supports patterns (?var): e.g. repeat change (fun x => ?f x) with f would eta-reduce all the functions (of arbitrary arity) in the goal.
  • One way to implement a tactic that sleeps for n seconds is in Sleep.v.
  • Some tactics take an "occurrence clause" to select where they apply. The common ones are in * and in H to apply everywhere and in a specific hypotheses, but there are actually a bunch of forms, for example:
    • in H1, H2 (just H1 and H2)
    • in H1, H2 |- * (H1, H2, and the goal)
    • in * |- (just hypotheses)
    • in |- (nowhere)
    • in |- * (just the goal, same as leaving the whole thing off)
    • in * |- * (everywhere, same as in *) These forms would be especially useful if occurrence clauses were first-class objects; that is, if tactics could take and pass occurrence clauses. Currently user-defined tactics support occurrence clauses via a set of tactic notations.
  • You can use notations to shorten repetitive Ltac patterns (much like Haskell's PatternSynonyms). Define a notation with holes (underscores) and use it in an Ltac match, eg Notation anyplus := (_ + _). and then
    match goal with
    | |- context[anyplus] => idtac
    end
    
    I would recommend using Local Notation so the notation isn't available outside the current file.
  • You can make all constructors of an inductive hints with Hint Constructors; you can also do this locally in a proof with eauto using t where t is the name of the inductive.
  • The intuition tactic has some unexpected behaviors. It takes a tactic to run on each goal, which is auto with * by default, using hints from all hint databases. intuition idtac or intuition eauto are both much safer. When using these, note that intuition eauto; simpl is parsed as intuition (eauto; simpl), which is unlikely to be what you want; you'll need to instead write (intuition eauto); simpl.
  • The Coq.Program.Tactics library has a number of useful tactics and tactic helpers. Some gems that I like: add_hypothesis is like pose proof but fails if the fact is already in the context (a lightweight version of the learn approach); destruct_one_ex implements the tricky code to eliminate an exists while retaining names (it's a better version of our deex); on_application matches any application of f by simply handling a large number of arities.
  • You can structure your proofs using bullets. You should use them in the order -, +, * so that Proof General indents them correctly. If you need more bullets you can keep going with --, ++, ** (although you should rarely need more then three levels of bullets in one proof).
  • You can use the set tactic to create shorthand names for expressions. These are special let-bound variables and show up in the hypotheses as v := def. To "unfold" these definitions you can do subst v (note the explicit name is required, subst will not do this by default). This is a good way to make large goals readable, perhaps while figuring out what lemma to extract. It can also be useful if you need to refer these expressions.
  • When you write a function in proof mode (useful when dependent types are involved), you probably want to end the proof with Defined instead of Qed. The difference is that Qed makes the proof term opaque and prevents reduction, while Defined will simplify correctly. If you mix computational parts and proof parts (eg, functions which produce sigma types) then you may want to separate the proof into a lemma so that it doesn't get unfolded into a large proof term.
  • To make an evar an explicit goal, you can use this trick: unshelve (instantiate (1:=_)). The way this work is to instantiate the evar with a fresh evar (created due to the _) and then unshelve that evar, making it an explicit goal. See UnshelveInstantiate.v for a working example.
  • The enough tactic behaves like assert but puts the goal for the stated fact after the current goal rather than before.
  • You can use context E [x] to bind a context variable, and then let e := eval context E [y] in ... to substitute back into the context. See Context.v for an example.
  • If you have a second-order match (using @?z x, which bind z to a function) and you want to apply the function, there's a trick involving a seemingly useless match. See LtacGallinaApplication.v for an example.
  • auto with foo nocore with the pseudo-database nocore disables the default core hint databases and only uses hints from foo (and the context).
  • If you need to apply a theorem to a hypothesis and then immediately destruct the result, there's a concise way to do it without repetition: apply thm in H as [x H], for example, might be used then thm produces an existential for a variable named x.
  • If you have a hypothesis H: a = b and need f a = f b, you can use apply (f_equal f) in H. (Strictly speaking this is just using the f_equal theorem in the standard library, but it's also very much like the inverse direction for the f_equal tactic.)
  • If you want to both run Ltac and return a constr, you can do so by wrapping the side effect in let _ := match goal with _ => side_effect_tactic end in .... See https://stackoverflow.com/questions/45949064/check-for-evars-in-a-tactic-that-returns-a-value/46178884#46178884 for Jason Gross's much more thorough explanation.
  • If you want lia to help with non-linear arithmetic involving division or modulo (or the similar quot and rem), you can do that for simple cases with Ltac Zify.zify_post_hook ::= Z.div_mod_to_equations. See DivMod.v for an example and the micromega documentation the full details.
  • Coq's admit will force you to use Admitted. If you want to use Qed, you can instead use Axiom falso : False. Ltac admit := destruct falso. This can be useful for debugging Qed errors (say, due to universes) or slow Qeds.

Gallina

  • tactics in terms, eg ltac:(eauto) can provide a proof argument

  • maximally inserted implicit arguments are implicit even when for identifier alone (eg, nil is defined to include the implicit list element type)

  • maximally inserted arguments can be defined differently for different numbers of arguments - undocumented but eq_refl provides an example

  • r.(Field) syntax: same as Field r, but convenient when Field is a projection function for the (record) type of r. If you use these, you might also want Set Printing Projections so Coq re-prints calls to projections with the same syntax.

  • Function vernacular provides a more advanced way to define recursive functions, which removes the restriction of having a structurally decreasing argument; you just need to specify a well-founded relation or a decreasing measure maps to a nat, then prove all necessary obligations to show this function can terminate. See manual and examples in Function.v for more details.

    Two alternatives are considerable as drop-in replacements for Function.

  • One can pattern-match on tuples under lambdas: Definition fst {A B} : (A * B) -> A := fun '(x,_) => x.

  • Records fields can be defined with :>, which make that field accessor a coercion. There are three ways to use this (since there are three types of coercion classes). See Coercions.v for some concrete examples.

    • If the field is an ordinary type, the record can be used as that type (the field will implicitly be accessed). One good use case for this is whenever a record includes another record; this coercion will make the field accessors of the sub-record work for the outer record as well. (This is vaguely similar to Go embedded structs)
    • If the field has a function type, the record can be called.
    • If the field is a sort (eg, Type), then the record can be used as a type.
  • When a Class field (as opposed to a record) is defined with :>, it becomes a hint for typeclass resolution. This is useful when a class includes a "super-class" requirement as a field. For example, Equivalence has fields for reflexivity, symmetry, and transitivity. The reflexivity field can be used to generically take an Equivalence instance and get a reflexivity instance for free.

  • The type classes in RelationClasses are useful but can be repetitive to prove. RelationInstances.v goes through a few ways of making these more convenient, and why you would want to do so (basically you can make reflexivity, transitivity, and symmetry more powerful).

  • The types of inductives can be definitions, as long as they expand to an "arity" (a function type ending in Prop, Set, or Type). See ArityDefinition.v.

  • "Views" are a programming pattern that can be used to perform a case analysis only on "relevant" parts of a datatype given the context of the case analysis. See Views.v.

  • Record fields that are functions can be written in definition-style syntax with the parameters bound after the record name, eg {| func x y := x + y; |} (see RecordFunction.v for a complete example).

  • If you have a coercion get_function : MyRecord >-> Funclass you can use Add Printing Coercion get_function and then add a notation for get_function so your coercion can be parsed as function application but printed using some other syntax (and maybe you want that syntax to be printing only).

  • You can pass implicit arguments explicitly in a keyword-argument-like style, eg nil (A:=nat). Use About to figure out argument names.

  • If you do nasty dependent pattern matches or use inversion on a goal and it produces equalities of existT's, you may benefit from small inversions, described in this blog post. While the small inversion tactic is still not available anywhere I can find, some support is built in to Coq's match return type inference; see SmallInversions.v for examples of how to use that.

  • You can use tactics-in-terms with notations to write function-like definitions that are written in Ltac. For example, you can use this facility to write macros that inspect and transform Gallina terms, producing theorem statements and optionally their proofs automatically. A simple example is given in DefEquality.v of writing a function that produces an equality for unfolding a definition.

  • Notations can be dangerous since they by default have global scope and are imported by Import, with no way to selectively import. A pattern I now use by default to make notations controllable is to define every notation in a module with a scope; see NotationModule.v.

    This pattern has several advantages:

    • notations are only loaded as needed, preventing conflicts when not using the notations
    • the notations can be brought into scope everywhere as needed with Import and Local Open Scope, restoring the convenience of a global notation
    • if notations conflict, some of them can always be scoped appropriately
  • Coq has a module system, modeled after ML (eg, the one used in OCaml). You can see some simple examples of using it in Modules.v. In user code, I've found modules to be more trouble than their worth 90% of the time - the biggest issue is that once something is in a module type, the only way to extend it is with a new module that wraps an existing module, and the only way to use the extension is to instantiate it. At the same time, you can mostly simulate module types with records.

  • Coq type class resolution is extremely flexible. There's a hint database called typeclass_instances and typeclass resolution is essentially eauto with typeclass_instances. Normally you add to this database with commands like Instance, but you can add whatever you want to it, including Hint Externs. See coq-record-update for a practical example.

  • Classes are a bit special compared to any other type. First of all, in (_ : T x1 x2) Coq will only trigger type class resolution to fill the hole when T is a class. Second, classes get special implicit generalization behavior; specifically, you can write {T} and Coq will automatically generalize the arguments to T, which you don't even have to write down. See the manual on implicit generalization for more details. Note that you don't have to use Class at declaration time to make something a class; you can do it after the fact with Existing Class T.

Other Coq commands

  • Search vernacular variants; see Search.v for examples.

  • Search s -Learnt for a search of local hypotheses excluding Learnt

  • Locate can search for notation, including partial searches.

  • Optimize Heap (undocumented) runs GC (specifically Gc.compact)

  • Optimize Proof (undocumented) runs several simplifications on the current proof term (see Proofview.compact)

  • (in Coq 8.12 and earlier) Generalizable Variable A enables implicit generalization; Definition id `(x:A) := x will implicitly add a parameter A before x. Generalizable All Variables enables implicit generalization for any identifier. Note that this surprisingly allows generalization without a backtick in Instances. Issue #6030 generously requests this behavior be documented, but it should probably require enabling some option. This has been fixed in Coq 8.13; the old behavior requires Set Instance Generalized Output. In Coq 8.14 the option has been removed.

  • Check supports partial terms, printing a type along with a context of evars. A cool example is Check (id _ _), where the first underscore must be a function (along with other constraints on the types involved).

  • The above also works with named existentials. For example, Check ?[x] + ?[y] works.

  • Unset Intuition Negation Unfolding will cause intuition to stop unfolding not.

  • Definitions can be normalized (simplified/computed) easily with Definition bar := Eval compute in foo.

  • Set Uniform Inductive Parameters (in Coq v8.9+beta onwards) allows you to omit the uniform parameters to an inductive in the constructors.

  • Lemma and Theorem are synonymous, except that coqdoc will not show lemmas. Also synonymous: Corollary, Remark, and Fact. Definition is nearly synonymous, except that Theorem x := def is not supported (you need to use Definition).

  • Sections are a powerful way to write a collection of definitions and lemmas that all take the same generic arguments. Here are some tricks for working with sections, which are illustrated in Sections.v:

    • Use Context, which is strictly more powerful than Variable - you can declare multiple dependent parameters and get type inference, and can write {A} to make sure a parameter is implicit and maximally inserted.
    • Tactics and hints are cleared at the end of a section. This is often annoying but you can take advantage of it by writing one-off tactics like t that are specific to the automation of a file, and callers don't see it. Similarly with adding hints to core with abandon.
    • Use notations and implicit types. Say you have a section that defines lists, and you want another file with a bunch of list theorems. You can start with Context (A:Type). Notation list := (List.list A). Implicit Types (l:list). and then in the whole section you basically never need to write type annotations. The notation and implicit type disappears at the end of the section so no worries about leaking it. Furthermore, don't write Theorem foo : forall l, but instead write Theorem foo l :; you can often also avoid using intros with this trick (though be careful about doing induction and ending up with a weak induction hypothesis).
    • If you write a general-purpose tactic t that solves most goals in a section, it gets annoying to write Proof. t. Qed. every time. Instead, define Notation magic := ltac:(t) (only parsing). and write Definition foo l : l = l ++ [] := magic.. You do unfortunately have to write Definition; Lemma and Theorem do not support := definitions. You don't have to call it magic but of course it's more fun that way. Note that this isn't the best plan because you end up with transparent proofs, which isn't great; ideally Coq would just support Theorem foo := syntax for opaque proofs.
  • Haskell has an operator f $ x, which is the same as f x except that its parsed differently: f $ 1 + 1 means f (1 + 1), avoiding parentheses. You can simulate this in Coq with a notation: Notation "f $ x" := (f x) (at level 60, right associativity, only parsing). (from jwiegley/coq-haskell).

  • A useful convention for notations is to have them start with a word and an exclamation mark. This is borrowed from @andres-erbsen, who borrowed it from the Rust macro syntax. An example of using this convention is in Macros.v. There are three big advantages to this approach: first, using it consistently alerts readers that a macro is being used, and second, using names makes it much easier to create many macros compared to inventing ASCII syntax, and third, starting every macro with a keyword makes them much easier to get parsing correctly.

  • To declare an axiomatic instance of a typeclass, use Declare Instance foo : TypeClass. This better than the pattern of Axiom + Existing Instance.

  • To make Ltac scripts more readable, you can use Set Default Goal Selector "!"., which will enforce that every Ltac command (sentence) be applied to exactly one focused goal. You achieve that by using a combination of bullets and braces. As a result, when reading a script you can always see the flow of where multiple goals are generated and solved.

  • Arguments foo _ & _ (in Coq 8.11) adds a bidirectionality hint saying that an application of foo should infer a type from its arguments after typing the first argument. See Bidirectional.v for an example and the latest Coq documentation.

  • Coq 8.11 introduced compiled interfaces, aka vos files (as far as I can tell there are a more principled replacement for vio files). Suppose you make a change deep down to Lib.v and want to start working on Proof.v which imports Lib.v through many dependencies. With vos files, you can recompile all the signatures that Proof.v depends on, skippinng proofs, and keep working. The basic way to use them is to compile Proof.required_vos, a special dependency coqdep generates that will build everything needed to work on Proof.v. Coq natively looks for vos files in interactive mode, and uses empty vos files to indicate that the file is fully compiled in a vo file.

    Note that Coq also has vok files; it's possible to check the missing proofs in a vos file, but this does not produce a vo and so all Coq can do is record that the proofs have been checked. They can also be compiled in parallel within a single file, although I don't know how to do that. Compiling voks lets you fairly confidently check proofs, but to really check everything (particularly universe constraints) you need to build vo files from scratch.

    Signature files have one big caveat: if Coq cannot determine the type of a theorem or the proof ends with Defined (and thus might be relevant to later type-checking), it has to run the proof. It does so silently, potentially eliminating any performance benefit. The main reason this happens is due to proofs in a section that don't annotate which section variables are used with Proof using. Generally this can be fixed with Set Default Proof Using "Type", though only on Coq master and not on Coq 8.11.0.

  • Coq 8.12+alpha has a new feature Set Printing Parentheses that prints parentheses as if no notations had an associativity. For example, this will print (1,2,3) as ((1,2),3). This is much more readable than entirely disabling notations.

  • You can use Export Set to set options in a way that affects any file directly importing the file (but not transitively importing, the way Global Set works). This allows a project to locally set up defaults with an options.v file with all of its options, which every file imports. You can use this for basic sanity settings, like Set Default Proof Using "Type". and Set Default Goal Selector "!" without forcing them on all projects that import your project.

  • You can use all: fail "goals remaining". to assert that a proof is complete. This is useful when you'll use Admitted. but want to document (and check in CI) that the proof is complete other than the admit. tactics used.

  • You can also use Fail idtac. to assert that a proof is complete, which is shorter than the above but more arcane.

  • You can use Fail Fail Qed. to really assert that a proof is complete, including doing universe checks, but then still be able to Restart it. I think this is only useful for illustrating small examples but it's amusing that it works. (The new Succeed vernacular in Coq 8.15 is a better replacement, because it preserves error messages on failure.)

  • Hints can now be set to global, export, or local. Global (the current default) means the hint applies to any module that transitivity imports this one; export makes the hint visible only if the caller imports this module directly. The behavior will eventually change for hints at the top-level so that they become export instead of global (see coq/coq#13384), so this might be worth understanding now. HintLocality.v walks through what the three levels do.

Using Coq

  • You can pass -noinit to coqc or coqtop to avoid loading the standard library.
  • Ltac is provided as a plugin loaded by the standard library; to load it you need Declare ML Module "ltac_plugin". (see NoInit.v).
  • Numeral notations are only provided by the prelude, even if you issue Require Import Coq.Init.Datatypes.
  • If you use Coq master, the latest Coq reference manual is built and deployed to https://coq.github.io/doc/master/refman/index.html automatically.

More Repositories

1

vscoq

A Visual Studio Code extension for Coq [maintainers=@rtetley,@huynhtrankhanh,@thery,@Blaisorblade]
OCaml
333
star
2

awesome-coq

A curated list of awesome Coq libraries, plugins, tools, verification projects, and resources [maintainer=@palmskog]
304
star
3

math-classes

A library of abstract interfaces for mathematical structures in Coq [maintainer=@spitters,@Lysxia]
Coq
160
star
4

fourcolor

Formal proof of the Four Color Theorem [maintainer=@ybertot]
Coq
158
star
5

coq-ext-lib

A library of Coq definitions, theorems, and tactics. [maintainers=@gmalecha,@liyishuai]
Coq
126
star
6

corn

Coq Repository at Nijmegen [maintainers=@spitters,@VincentSe,@Lysxia]
Coq
108
star
7

coq-art

Coq code and exercises from the Coq'Art book [maintainers=@ybertot,@Casteran]
Coq
107
star
8

coq-dpdgraph

Build dependency graphs between Coq objects [maintainers=@Karmaki,@ybertot]
Coq
86
star
9

manifesto

Documentation on goals of the coq-community organization, the shared contributing guide and code of conduct.
68
star
10

coqeal

The Coq Effective Algebra Library [maintainers=@CohenCyril,@proux01]
Coq
65
star
11

hydra-battles

Variations on Kirby & Paris' hydra battles and other entertaining math in Coq (collaborative, documented, includes exercises) [maintainer=@Casteran]
Coq
63
star
12

coq-100-theorems

Statements of famous theorems proven in Coq [maintainer=@jmadiot]
HTML
55
star
13

autosubst

Automation for de Bruijn syntax and substitution in Coq [maintainers=@RalfJung,@co-dan]
Coq
51
star
14

topology

General topology in Coq [maintainers=@amiloradovsky,@Columbus240,@stop-cran]
Coq
46
star
15

semantics

A survey of semantics styles in Coq, from natural semantics through structural operational, axiomatic, and denotational semantics, to abstract interpretation [maintainer=@k4rtik]
Coq
45
star
16

fav-ssr

Functional Algorithms Verified in SSReflect [maintainer=@clayrat]
Coq
45
star
17

paramcoq

Coq plugin for parametricity [maintainer=@proux01]
Coq
44
star
18

dedekind-reals

A formalization of the Dedekind real numbers in Coq [maintainer=@andrejbauer]
Coq
43
star
19

parseque

Total Parser Combinators in Coq [maintainer=@womeier]
Coq
42
star
20

reglang

Regular Language Representations in Coq [maintainers=@chdoc,@palmskog]
Coq
42
star
21

docker-coq

Docker images of the Coq proof assistant (see also: https://github.com/coq-community/docker-coq-action) [maintainers=@erikmd,@himito]
Dockerfile
37
star
22

coqdocjs

Collection of scripts to improve the output of coqdoc [maintainers=@chdoc,@palmskog]
JavaScript
36
star
23

coqffi

Automatically generates Coq FFI bindings to OCaml libraries [maintainer=@lthms]
OCaml
33
star
24

coq-nix-toolbox

Nix helper scripts to automate local builds and CI [maintainers=@CohenCyril,@Zimmi48]
Nix
32
star
25

graph-theory

Graph Theory [maintainers=@chdoc,@damien-pous]
Coq
32
star
26

chapar

A framework for verification of causal consistency for distributed key-value stores and their clients in Coq [maintainer=@palmskog]
Coq
32
star
27

aac-tactics

Coq plugin providing tactics for rewriting universally quantified equations, modulo associative (and possibly commutative) operators [maintainer=@palmskog]
OCaml
29
star
28

goedel

Archived since the contents have been moved to the Hydras & Co. repository
Coq
29
star
29

gaia

Implementation of books from Bourbaki's Elements of Mathematics in Coq [maintainer=@thery]
Coq
28
star
30

dblib

Coq library for working with de Bruijn indices [maintainer=@KevOrr]
Coq
28
star
31

coq-program-verification-template

Template project for program verification in Coq, showcasing reasoning on CompCert's Clight language using the Verified Software Toolchain [maintainer=@palmskog]
Coq
27
star
32

lemma-overloading

Libraries demonstrating design patterns for programming and proving with canonical structures in Coq [maintainer=@anton-trunov]
Coq
26
star
33

alea

Coq library for reasoning on randomized algorithms [maintainers=@anton-trunov,@volodeyka]
Coq
25
star
34

atbr

Coq library and tactic for deciding Kleene algebras [maintainer=@tchajed]
Coq
23
star
35

bits

A formalization of bitset operations in Coq and the corresponding axiomatization and extraction to OCaml native integers [maintainer=@anton-trunov]
Coq
22
star
36

bignums

Coq library of arbitrarily large numbers, providing BigN, BigZ, BigQ that used to be part of the standard library [maintainers=@proux01,@erikmd]
Coq
22
star
37

coqoban

Sokoban (in Coq) [maintainer=@erikmd]
Coq
21
star
38

sudoku

A certified Sudoku solver in Coq [maintainers=@siraben,@thery]
Coq
20
star
39

HighSchoolGeometry

Geometry in Coq for French high school [maintainer=@thery]
Coq
19
star
40

apery

A formal proof of the irrationality of zeta(3), the Apéry constant [maintainer=@amahboubi,@pi8027]
Coq
19
star
41

hoare-tut

A Tutorial on Reflecting in Coq the generation of Hoare proof obligations [maintainer=@k4rtik]
Coq
19
star
42

coq-plugin-template

Template project for Coq plugins using the Dune build system, showcasing some advanced features [maintainer=@ejgallego]
OCaml
17
star
43

trocq

A modular parametricity plugin for proof transfer in Coq [maintainers=@CohenCyril,@ecranceMERCE,@amahboubi]
Coq
17
star
44

metaprogramming-rosetta-stone

A rosetta stone for metaprogramming in Coq, with different examples of tactics, plugins, etc implemented in different metaprogramming languages [maintainer=@yforster]
Coq
16
star
45

coqtail-math

Coqtail is a library of mathematical theorems and tools proved inside the Coq proof assistant. Results range mostly from arithmetic to real and complex analysis. [maintainer=@jmadiot]
Coq
15
star
46

huffman

Correctness proof of the Huffman coding algorithm in Coq [maintainer=@palmskog]
Coq
14
star
47

templates

Templates for configuration files and scripts useful for maintaining Coq projects [maintainers=@palmskog,@Zimmi48]
Mustache
13
star
48

tarjan

Coq formalization of algorithms due to Tarjan and Kosaraju for finding strongly connected graph components using Mathematical Components and SSReflect [maintainers=@CohenCyril,@palmskog]
Coq
13
star
49

regexp-Brzozowski

Coq formalization of decision procedures for regular expression equivalence [maintainer=@anton-trunov]
Coq
12
star
50

qarith-stern-brocot

Binary rational numbers in Coq [maintainer=@herbelin]
Coq
12
star
51

docker-coq-action

GitHub Action using Docker-Coq [maintainers=@erikmd,@Zimmi48]
Shell
12
star
52

mmaps

Modular Finite Maps over Ordered Types in Coq [maintainers=@letouzey,@palmskog]
Coq
10
star
53

notation-gallery

Examples showing best practices for using Coq notations and custom entries [maintainer=@bcpierce00]
Coq
9
star
54

comp-dec-modal

Completeness and Decidability of Modal Logic Calculi [maintainer=@chdoc]
Coq
8
star
55

buchberger

Verified implementation in Coq of Buchberger's algorithm for computing Gröbner bases [maintainer=@palmskog]
Coq
8
star
56

proviola

Tool for reanimation of Coq proofs [maintainer=@JasonGross]
Python
7
star
57

coq-performance-tests

A library of Coq source files testing for performance regressions on Coq [maintainer=@JasonGross]
Coq
7
star
58

generic-environments

Coq library that provides an abstract data type for environments [maintainer=@aerabi]
Coq
6
star
59

zorns-lemma

Archived since the contents have been moved to the topology repository
Coq
6
star
60

reduction-effects

A Coq plugin to add reduction side effects to some Coq reduction strategies [maintainers=@liyishuai,@JasonGross]
Makefile
6
star
61

docker-base

Parent image for Docker images of the Coq proof assistant [maintainers=@erikmd,@himito]
Dockerfile
4
star
62

almost-full

Coq development of almost-full relations, including the Ramsey Theorem, useful for proving termination [maintainer=@palmskog]
Coq
3
star
63

jmlcoq

Coq definition of JML and a verified runtime assertion checker [maintainer=@palmskog]
Coq
3
star
64

bertrand

Coq proof of Bertrand's postulate on existence of primes [maintainer=@thery]
Coq
3
star
65

run-coq-bug-minimizer

Repository for triggering runs of the Coq bug minimizer using GitHub Actions [maintainer=@JasonGross]
Shell
2
star
66

pocklington

Pocklington's criterion for primality in Coq [maintainer=@Casteran]
Coq
2
star
67

vscoq-legacy

Legacy Visual Studio Code extension for Coq [maintainers=@huynhtrankhanh,@thery,@Blaisorblade]
TypeScript
1
star
68

stalmarck

Certified implementation in Coq of Stålmarck's algorithm for proving tautologies [maintainer=@palmskog]
Coq
1
star
69

exact-real-arithmetic

Exact Real Arithmetic [maintainers=@ybertot,@magaud]
Coq
1
star