commit
6d8f62d529
5 changed files with 264 additions and 13 deletions
15
README.md
15
README.md
|
@ -80,24 +80,15 @@ squished beneath it.
|
||||||
|
|
||||||
## Fonts in Emacs
|
## Fonts in Emacs
|
||||||
|
|
||||||
It is recommended that you add the following to the end of your emacs
|
It is recommended that you install the font [mononoki](https://madmalik.github.io/mononoki/), and add the following to the end of your emacs configuration file at `~/.emacs`:
|
||||||
configuration file at `~/.emacs`, if you have the mentioned fonts available:
|
|
||||||
|
|
||||||
``` elisp
|
``` elisp
|
||||||
;; Setting up Fonts for use with Agda/PLFA
|
;; default to mononoki
|
||||||
;;
|
|
||||||
;; default to DejaVu Sans Mono,
|
|
||||||
(set-face-attribute 'default nil
|
(set-face-attribute 'default nil
|
||||||
:family "DejaVu Sans Mono"
|
:family "mononoki"
|
||||||
:height 120
|
:height 120
|
||||||
:weight 'normal
|
:weight 'normal
|
||||||
:width 'normal)
|
:width 'normal)
|
||||||
|
|
||||||
;; fix \:
|
|
||||||
(set-fontset-font "fontset-default"
|
|
||||||
(cons (decode-char 'ucs #x2982)
|
|
||||||
(decode-char 'ucs #x2982))
|
|
||||||
"STIX")
|
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -1,4 +1,9 @@
|
||||||
// Define variables for code formatting
|
// Define variables for code formatting
|
||||||
|
@font-face {
|
||||||
|
font-family: 'mononoki';
|
||||||
|
src: url('fonts/mononoki.woff2') format('woff2'),
|
||||||
|
url('fonts/mononoki.woff') format('woff');
|
||||||
|
}
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: 'DejaVu Sans Mono';
|
font-family: 'DejaVu Sans Mono';
|
||||||
src: url('fonts/DejaVuSansMono.woff2') format('woff2'),
|
src: url('fonts/DejaVuSansMono.woff2') format('woff2'),
|
||||||
|
@ -16,7 +21,7 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
@mixin code-font {
|
@mixin code-font {
|
||||||
font-family: 'DejaVu Sans Mono', 'Source Code Pro', 'Bitstream Vera Sans Mono', 'FreeMono', 'Courier New', 'Monaco', 'Menlo', monospace, serif;
|
font-family: 'mononoki', 'DejaVu Sans Mono', 'Source Code Pro', 'Bitstream Vera Sans Mono', 'FreeMono', 'Courier New', 'Monaco', 'Menlo', monospace, serif;
|
||||||
font-size: .85em;
|
font-size: .85em;
|
||||||
}
|
}
|
||||||
@mixin code-container {
|
@mixin code-container {
|
||||||
|
|
BIN
assets/fonts/mononoki.woff
Normal file
BIN
assets/fonts/mononoki.woff
Normal file
Binary file not shown.
BIN
assets/fonts/mononoki.woff2
Normal file
BIN
assets/fonts/mononoki.woff2
Normal file
Binary file not shown.
255
style-guide.md
Normal file
255
style-guide.md
Normal file
|
@ -0,0 +1,255 @@
|
||||||
|
Style guide for PLFA
|
||||||
|
============================
|
||||||
|
|
||||||
|
This is based on [the style guide for the Agda standard library](https://github.com/agda/agda-stdlib/blob/master/notes/style-guide.md).
|
||||||
|
Like it, this is very much a work-in-progress and is not exhaustive.
|
||||||
|
|
||||||
|
## File structure
|
||||||
|
|
||||||
|
#### Module imports
|
||||||
|
|
||||||
|
* All module imports should be placed at the top of the file immediately
|
||||||
|
after the module declaration.
|
||||||
|
|
||||||
|
* If the module takes parameters that require imports from other files
|
||||||
|
then those imports only may be placed above the module declaration.
|
||||||
|
|
||||||
|
* If it is important that certain names only come into scope later in
|
||||||
|
the file then the module should still be imported at the top of the
|
||||||
|
file but it can be given a shorter name using `as` and then opened
|
||||||
|
later on in the file when needed, e.g.
|
||||||
|
```agda
|
||||||
|
import Data.List.Relation.Binary.Equality.Setoid as SetoidEquality
|
||||||
|
...
|
||||||
|
...
|
||||||
|
open SetoidEquality S
|
||||||
|
```
|
||||||
|
|
||||||
|
* The list of module imports should be in alphabetical order.
|
||||||
|
|
||||||
|
* When using only a few items from a module, the items should be
|
||||||
|
enumerated in the import with `using` in order to make dependencies
|
||||||
|
clearer.
|
||||||
|
|
||||||
|
#### Indentation
|
||||||
|
|
||||||
|
* The contents of a top-level module should have zero indentation.
|
||||||
|
|
||||||
|
* Every subsequent nested scope should then be indented by an additional
|
||||||
|
two spaces.
|
||||||
|
|
||||||
|
* `where` blocks should be indented by two spaces and their contents
|
||||||
|
should be aligned with the `where`.
|
||||||
|
|
||||||
|
* If the type of a term does not fit on one line then the subsequent
|
||||||
|
lines of the type should all be indented by two spaces, e.g.
|
||||||
|
```agda
|
||||||
|
map-cong₂ : ∀ {a b} {A : Set a} {B : Set b}
|
||||||
|
→ ∀ {f g : A → B} {xs}
|
||||||
|
→ All (λ x → f x ≡ g x) xs → map f xs ≡ map g xs
|
||||||
|
```
|
||||||
|
|
||||||
|
* As can be seen in the example above, function arrows at line breaks
|
||||||
|
should always go at the beginning of the next line rather than the
|
||||||
|
end of the line.
|
||||||
|
|
||||||
|
#### Module parameters
|
||||||
|
|
||||||
|
* Module parameters should be put on a single line if they fit.
|
||||||
|
|
||||||
|
* If they don't fit on a single line, then they should be spread out
|
||||||
|
over multiple lines, each indented by two spaces. If they can be
|
||||||
|
grouped logically by line then it is fine to do so, otherwise a line
|
||||||
|
each is probably clearest.
|
||||||
|
|
||||||
|
* The `where` should go on it's own line at the end.
|
||||||
|
|
||||||
|
* For example:
|
||||||
|
```agda
|
||||||
|
module Relation.Binary.Reasoning.Base.Single
|
||||||
|
{a ℓ} {A : Set a} (_∼_ : Rel A ℓ)
|
||||||
|
(refl : Reflexive _∼_) (trans : Transitive _∼_)
|
||||||
|
where
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Reasoning layout
|
||||||
|
|
||||||
|
* The `begin` clause should go on a new line.
|
||||||
|
|
||||||
|
* Every subsequent combinator `_≡⟨_⟩_` should go on its own line,
|
||||||
|
with the intermediate terms on their own line, indented by two spaces.
|
||||||
|
|
||||||
|
* The relation sign (e.g. `≡`) for each line should be aligned if possible.
|
||||||
|
|
||||||
|
* For example:
|
||||||
|
```agda
|
||||||
|
+-comm : Commutative _+_
|
||||||
|
+-comm zero n = sym (+-identityʳ n)
|
||||||
|
+-comm (suc m) n =
|
||||||
|
begin
|
||||||
|
suc m + n
|
||||||
|
≡⟨⟩
|
||||||
|
suc (m + n)
|
||||||
|
≡⟨ cong suc (+-comm m n) ⟩
|
||||||
|
suc (n + m)
|
||||||
|
≡⟨ sym (+-suc n m) ⟩
|
||||||
|
n + suc m
|
||||||
|
∎
|
||||||
|
```
|
||||||
|
|
||||||
|
* When multiple reasoning frameworks need to be used in the same file, the
|
||||||
|
`open` statement should always come in a where clause local to the
|
||||||
|
definition. This way users can easily see which reasoning toolkit is
|
||||||
|
being used. For instance:
|
||||||
|
```agda
|
||||||
|
foo m n p = begin
|
||||||
|
(...) ∎
|
||||||
|
where open ≤-Reasoning
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Record layout
|
||||||
|
|
||||||
|
* The `record` declaration should go on the same line as the rest of the proof.
|
||||||
|
|
||||||
|
* The next line with the first record item should start with a single `{`.
|
||||||
|
|
||||||
|
* Every subsequent item of the record should go on its own line starting with
|
||||||
|
a `;`.
|
||||||
|
|
||||||
|
* The final line should end with `}` on its own.
|
||||||
|
|
||||||
|
* For example:
|
||||||
|
```agda
|
||||||
|
≤-isPreorder : IsPreorder _≡_ _≤_
|
||||||
|
≤-isPreorder = record
|
||||||
|
{ isEquivalence = isEquivalence
|
||||||
|
; reflexive = ≤-reflexive
|
||||||
|
; trans = ≤-trans
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
#### `where` blocks
|
||||||
|
|
||||||
|
* `where` blocks are preferred rather than the `let` construction.
|
||||||
|
|
||||||
|
* The `where` should be placed on the line below the main proof,
|
||||||
|
indented by two spaces.
|
||||||
|
|
||||||
|
* If the contents of the block is non-trivial then types should be
|
||||||
|
provided alongside the terms, and all terms should be on lines after
|
||||||
|
the `where`, e.g.
|
||||||
|
```agda
|
||||||
|
statement : Statement
|
||||||
|
statement = proof
|
||||||
|
where
|
||||||
|
proof : Proof
|
||||||
|
proof = some-very-long-proof
|
||||||
|
```
|
||||||
|
|
||||||
|
* If the contents of the block is trivial or is an `open` statement then
|
||||||
|
it can provided on the same line as the `where` and a type can be
|
||||||
|
omitted, e.g.
|
||||||
|
```agda
|
||||||
|
statement : Statement
|
||||||
|
statement = proof
|
||||||
|
where proof = x
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Other
|
||||||
|
|
||||||
|
* Non-trivial proofs in `private` blocks are generally discouraged. If its
|
||||||
|
non-trivial then the chances are someone will want to reuse it as some
|
||||||
|
point!
|
||||||
|
|
||||||
|
* The `with` syntax is preferred over the use of `case` from the `Function`
|
||||||
|
module.
|
||||||
|
|
||||||
|
## Types
|
||||||
|
|
||||||
|
#### Implicit and explicit arguments
|
||||||
|
|
||||||
|
* Functions arguments should be implicit if they can "almost always"
|
||||||
|
be inferred. If there are common cases where they cannot be inferred
|
||||||
|
then they should be left explicit.
|
||||||
|
|
||||||
|
* If there are lots of implicit arguments that are common to a collection
|
||||||
|
of proofs they should be extracted by using an anonymous module.
|
||||||
|
|
||||||
|
* Implicit of type `Level` and `Set` can be generalised using `variable`.
|
||||||
|
At the moment the policy is *not* to generalise over any other types in
|
||||||
|
order to minimise the amount of information that users have to keep in
|
||||||
|
their head concurrently.
|
||||||
|
|
||||||
|
## Naming conventions
|
||||||
|
|
||||||
|
* Names should be descriptive - i.e. given the name of a proof and the
|
||||||
|
module it lives in then users should be able to make a reasonable
|
||||||
|
guess at what it contains.
|
||||||
|
|
||||||
|
* Terms from other modules should only be renamed to avoid name clashes,
|
||||||
|
otherwise all names should be used as defined.
|
||||||
|
|
||||||
|
* Datatype names should be capitalised and function names should be
|
||||||
|
lowercase.
|
||||||
|
|
||||||
|
#### Variables
|
||||||
|
|
||||||
|
* Natural variables are named `m`, `n`, `o`, ... (default `n`)
|
||||||
|
|
||||||
|
* Integer variables are named `i`, `j`, `k`, ... (default `i`)
|
||||||
|
|
||||||
|
* Rational variables are named `p`, `q`, `r`, ... (default `p`)
|
||||||
|
|
||||||
|
* When naming proofs, the variables should occur in order, e.g.
|
||||||
|
`m≤n+m` rather than `n≤m+n`.
|
||||||
|
|
||||||
|
* Collections of elements are usually indicated by appending an `s`
|
||||||
|
(e.g. if you are naming your variables `x` and `y` then lists
|
||||||
|
should be named `xs` and `ys`).
|
||||||
|
|
||||||
|
|
||||||
|
#### Preconditions and postconditions
|
||||||
|
|
||||||
|
* Preconditions should only be included in names of results if
|
||||||
|
"important" (mostly judgement call).
|
||||||
|
|
||||||
|
* Preconditions of results should be prepended to a description
|
||||||
|
of the result by using the symbol `⇒` in names (e.g. `asym⇒antisym`)
|
||||||
|
|
||||||
|
* Preconditions and postconditions should be combined using the symbols
|
||||||
|
`∨` and `∧` (e.g. `m*n≡0⇒m≡0∨n≡0`)
|
||||||
|
|
||||||
|
* Try to avoid the need for bracketing but if necessary use square
|
||||||
|
brackets (e.g. `[m∸n]⊓[n∸m]≡0`)
|
||||||
|
|
||||||
|
#### Operators and relations
|
||||||
|
|
||||||
|
* Operators and relations should be defined using mixfix notation where
|
||||||
|
applicable (e.g. `_+_`, `_<_`)
|
||||||
|
|
||||||
|
* Common properties such as those in rings/orders/equivalences etc.
|
||||||
|
have defined abbreviations (e.g. commutativity is shortened to `comm`).
|
||||||
|
`Data.Nat.Properties` is a good place to look for examples.
|
||||||
|
|
||||||
|
* Properties should be by prefixed by the relevant operator/relation
|
||||||
|
(e.g. commutativity of `_+_` is named `+-comm`)
|
||||||
|
|
||||||
|
* If the relevant unicode characters are available, negated forms of
|
||||||
|
relations should be used over the `¬` symbol (e.g. `m+n≮n` should be
|
||||||
|
used instead of `¬m+n<n`).
|
||||||
|
|
||||||
|
#### Functions and relations over specific datatypes
|
||||||
|
|
||||||
|
* When defining a new relation over a datatype
|
||||||
|
(e.g. `Data.List.Relation.Binary.Pointwise`)
|
||||||
|
it is often common to define how to introduce and eliminate that
|
||||||
|
relation over various simple functions (e.g. `map`) over that datatype:
|
||||||
|
```agda
|
||||||
|
map⁺ : Pointwise (λ a b → R (f a) (g b)) as bs →
|
||||||
|
Pointwise R (map f as) (map g bs)
|
||||||
|
|
||||||
|
map⁻ : Pointwise R (map f as) (map g bs) →
|
||||||
|
Pointwise (λ a b → R (f a) (g b)) as bs
|
||||||
|
```
|
||||||
|
Such elimination and introduction proofs are called the name of the
|
||||||
|
function superscripted with either a `+` or `-` accordingly.
|
Loading…
Reference in a new issue