Skip to content

Commit 1db9747

Browse files
Updated the style guide with some additional points
1 parent e9c6f57 commit 1db9747

File tree

1 file changed

+116
-50
lines changed

1 file changed

+116
-50
lines changed

notes/style-guide.md

Lines changed: 116 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,85 +3,151 @@ Style guide for the standard library
33

44
This is very much a work-in-progress and is not exhaustive.
55

6-
## Module imports
6+
## File structure
77

8-
* All module imports should be at the top of the file immediately after the module declaration.
8+
#### Module imports
99

10-
* When only using a few items from a module, the items should be enumerated in the import with `using`
11-
in order to make dependencies clearer.
10+
* All module imports should be at the top of the file immediately after
11+
the module declaration.
1212

13-
## Indentation
13+
* If it is important that certain names only come into scope later in
14+
the file then the module should still be imported at the top of the
15+
file but it can be given a shorter name using `as` and then opened
16+
later on in the file when needed, e.g.
17+
```agda
18+
import Data.List.Relation.Binary.Equality.SetoidEquality as SetoidEq
19+
...
20+
...
21+
open SetoidEq
22+
```
23+
24+
* The list of module imports should be in alphabetical order.
25+
26+
* When only using a few items from a module, the items should be
27+
enumerated in the import with `using` in order to make dependencies
28+
clearer.
29+
30+
#### Indentation
31+
32+
* The contents of a top-level module should have zero indentation.
33+
34+
* Every subsequent nested scope should then indent by 2 spaces.
35+
36+
* `where` blocks should be indented two spaces in and their contents
37+
should be aligned with the `where`.
1438

15-
* The top-level contents of a top-level module should have zero indentation. Every subsequent
16-
level of indentation should use 2 spaces.
39+
* If the type of a term does not fit on one line then the subsequent
40+
lines of the type should all be aligned with the first character
41+
of the first line of type, e.g.
42+
```agda
43+
map-cong₂ : ∀ {a b} {A : Set a} {B : Set b} →
44+
∀ {f g : A → B} {xs} →
45+
All (λ x → f x ≡ g x) xs → map f xs ≡ map g xs
46+
```
47+
48+
* As can be seen in the example above, function arrows at line breaks
49+
should always go at the end of the line rather the beginning of the
50+
next line.
51+
52+
#### Reasoning layout
1753

18-
* `where` blocks should be indented two spaces in and their contents should be aligned with the `where`.
54+
* The `begin` clause should go on the same line as the rest of the proof.
55+
56+
* Every subsequent combinator `_≡⟨_⟩_` should go on it's own line,
57+
indented by two spaces.
58+
59+
* The relation sign (e.g. ``) for each line should be aligned if possible.
60+
61+
* For example:
62+
```agda
63+
+-comm : Commutative _+_
64+
+-comm zero n = sym (+-identityʳ n)
65+
+-comm (suc m) n = begin
66+
suc m + n ≡⟨⟩
67+
suc (m + n) ≡⟨ cong suc (+-comm m n) ⟩
68+
suc (n + m) ≡⟨ sym (+-suc n m) ⟩
69+
n + suc m ∎
70+
```
71+
72+
#### Other
73+
74+
* Non-trivial proofs in `private` blocks are generally discouraged.
75+
76+
* `where` blocks are preferred rather than the `let` construction.
77+
78+
* The `with` syntax is preferred over the use of `case` from the `Function`
79+
module.
80+
81+
## Types
1982

2083
## Implicit and explicit arguments
2184

22-
* Functions arguments should be implicit if they can "almost always" be inferred. If there are common
23-
cases where they cannot be inferred then they should be left explicit.
85+
* Functions arguments should be implicit if they can "almost always"
86+
be inferred. If there are common cases where they cannot be inferred
87+
then they should be left explicit.
2488

25-
* If there are lots of implicit arguments that are common to a set of proofs they should be
26-
extracted by using an anonymous module (or possibly the new `variable` keyword in Agda 2.6.0).
89+
* If there are lots of implicit arguments that are common to a collection
90+
of proofs they should be extracted by using an anonymous module (or
91+
possibly the new `variable` keyword in Agda 2.6.0).
2792

2893
## Naming conventions
2994

30-
* Names should be descriptive - i.e. given the name of a proof and the module it lives in
31-
then users should be able to make a reasonable guess at what it contains.
95+
* Names should be descriptive - i.e. given the name of a proof and the
96+
module it lives in then users should be able to make a reasonable
97+
guess at what it contains.
98+
99+
* Terms from other modules should only be renamed to avoid name clashes,
100+
otherwise all names should be used as defined.
32101

33-
* Datatype names should be capitalised and function names should be lowercase.
102+
* Datatype names should be capitalised and function names should be
103+
lowercase.
34104

35-
* Collections of elements are usually indicated by appending an `s` (e.g. if you are naming your
36-
variables `x` and `y` then a lists should be named `xs` and `ys`).
105+
* Collections of elements are usually indicated by appending an `s`
106+
(e.g. if you are naming your variables `x` and `y` then lists
107+
should be named `xs` and `ys`).
37108

38109
#### Preconditions and postconditions
39110

40-
* Preconditions should only be included in names of results if "important" (mostly judgement call).
111+
* Preconditions should only be included in names of results if
112+
"important" (mostly judgement call).
41113

42-
* Preconditions of results should be prepended to a description of the result by using the
43-
symbol `` in names (e.g. `asym⇒antisym`)
114+
* Preconditions of results should be prepended to a description
115+
of the result by using the symbol `` in names (e.g. `asym⇒antisym`)
44116

45-
* Preconditions and postconditions should be combined using the symbols `` and `` (e.g. `i*j≡0⇒i≡0∨j≡0`)
117+
* Preconditions and postconditions should be combined using the symbols
118+
`` and `` (e.g. `i*j≡0⇒i≡0∨j≡0`)
46119

47-
* Try to avoid the need for bracketing but if necessary use square brackets (e.g. `[m∸n]⊓[n∸m]≡0`)
120+
* Try to avoid the need for bracketing but if necessary use square
121+
brackets (e.g. `[m∸n]⊓[n∸m]≡0`)
48122

49123
#### Operators and relations
50124

51-
* Operators and relations names should use mixfix notation where applicable (e.g. `_+_`, `_<_`)
125+
* Operators and relations names should use mixfix notation where
126+
applicable (e.g. `_+_`, `_<_`)
52127

53-
* Common properties such as those in rings/orders/equivalences etc. have defined abbreviations
54-
(e.g. commutativity is shortened to `comm`). `Data.Nat.Properties` is a good place to look for examples.
128+
* Common properties such as those in rings/orders/equivalences etc.
129+
have defined abbreviations (e.g. commutativity is shortened to `comm`).
130+
`Data.Nat.Properties` is a good place to look for examples.
55131

56-
* Properties should be by prefixed by the relevant operator/relation (e.g. commutativity of `_+_` is named `+-comm`)
132+
* Properties should be by prefixed by the relevant operator/relation
133+
(e.g. commutativity of `_+_` is named `+-comm`)
57134

58-
* If the relevant unicode characters are available, negated forms of relations should be used over
59-
the `¬` symbol (e.g. `m+n≮n` should be used instead of `¬m+n<n`).
135+
* If the relevant unicode characters are available, negated forms of
136+
relations should be used over the `¬` symbol (e.g. `m+n≮n` should be
137+
used instead of `¬m+n<n`).
60138

61139
#### Functions and relations over specific datatypes
62140

63-
* When defining a new relation over a datatype (e.g. `Data.List.Relation.Binary.Pointwise`)
64-
it is often common to define how to introduce and eliminate that relation over various simple functions
65-
(e.g. `map`) over that datatype:
141+
* When defining a new relation over a datatype
142+
(e.g. `Data.List.Relation.Binary.Pointwise`)
143+
it is often common to define how to introduce and eliminate that
144+
relation over various simple functions (e.g. `map`) over that datatype:
66145
```agda
67-
map⁺ : Pointwise (λ a b → R (f a) (g b)) as bs → Pointwise R (map f as) (map g bs)
68-
map⁻ : Pointwise R (map f as) (map g bs) → Pointwise (λ a b → R (f a) (g b)) as bs
69-
```
70-
Such elimination and introduction proofs are called the name of the function superscripted with either
71-
a `+` or `-` accordingly.
72-
73-
## Other miscellaneous points
74-
75-
* `where` blocks are preferred rather than the `let` construction.
146+
map⁺ : Pointwise (λ a b → R (f a) (g b)) as bs →
147+
Pointwise R (map f as) (map g bs)
76148
77-
* If a type is split over two lines then the arrow should go at the end of the first line rather than
78-
the beginning of the second line, i.e.
79-
```
80-
foo : VeryLongType →
81-
B
82-
```
83-
rather than
84-
```
85-
foo : VeryLongType
86-
→ B
149+
map⁻ : Pointwise R (map f as) (map g bs) →
150+
Pointwise (λ a b → R (f a) (g b)) as bs
87151
```
152+
Such elimination and introduction proofs are called the name of the
153+
function superscripted with either a `+` or `-` accordingly.

0 commit comments

Comments
 (0)