Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Newer
Older
100644 412 lines (310 sloc) 9.586 kb
8f343b5 @tibbe Added a first version of the style guide.
authored
1 Haskell Style Guide
2 ===================
3
4 This is a short document describing the preferred coding style for
5 this project. I've tried to cover the major areas of formatting and
6 naming. When something isn't covered by this guide you should stay
7 consistent with the code in the other modules.
8
05330ba @tibbe Remove the ToC as numbered headings don't work well in Markdown
authored
9 Formatting
10 ----------
8f343b5 @tibbe Added a first version of the style guide.
authored
11
12 ### Line Length
13
14 Maximum line length is *80 characters*.
15
16 ### Indentation
17
18 Tabs are illegal. Use spaces for indenting. Indent your code blocks
19 with *4 spaces*. Indent the `where` keyword two spaces to set it
20 apart from the rest of the code and indent the definitions in a
21 `where` clause 2 spaces. Some examples:
22
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
23 ```haskell
24 sayHello :: IO ()
25 sayHello = do
26 name <- getLine
27 putStrLn $ greeting name
28 where
29 greeting name = "Hello, " ++ name ++ "!"
30
31 filter :: (a -> Bool) -> [a] -> [a]
32 filter _ [] = []
33 filter p (x:xs)
34 | p x = x : filter p xs
35 | otherwise = filter p xs
36 ```
8f343b5 @tibbe Added a first version of the style guide.
authored
37
38 ### Blank Lines
39
40 One blank line between top-level definitions. No blank lines between
41 type signatures and function definitions. Add one blank line between
42 functions in a type class instance declaration if the functions bodies
43 are large. Use your judgement.
44
45 ### Whitespace
46
47 Surround binary operators with a single space on either side. Use
19caa1d @jaspervdj Consistent spelling of "judgement".
jaspervdj authored
48 your better judgement for the insertion of spaces around arithmetic
8f343b5 @tibbe Added a first version of the style guide.
authored
49 operators but always be consistent about whitespace on either side of
50 a binary operator. Don't insert a space after a lambda.
51
52 ### Data Declarations
53
54 Align the constructors in a data type definition. Example:
55
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
56 ```haskell
57 data Tree a = Branch a (Tree a) (Tree a)
58 | Leaf
59 ```
8f343b5 @tibbe Added a first version of the style guide.
authored
60
a5e6086 @tibbe Formatting of data types with long type names
authored
61 For long type names the following formatting is also acceptable:
62
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
63 ```haskell
64 data HttpException
65 = InvalidStatusCode Int
66 | MissingContentHeader
67 ```
a5e6086 @tibbe Formatting of data types with long type names
authored
68
8f343b5 @tibbe Added a first version of the style guide.
authored
69 Format records as follows:
70
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
71 ```haskell
72 data Person = Person
25eaf48 @tibbe Add a section on dealing with laziness
authored
73 { firstName :: !String -- ^ First name
74 , lastName :: !String -- ^ Last name
75 , age :: !Int -- ^ Age
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
76 } deriving (Eq, Show)
77 ```
8f343b5 @tibbe Added a first version of the style guide.
authored
78
c261011 @jaspervdj Added section about list declarations.
jaspervdj authored
79 ### List Declarations
80
81 Align the elements in the list. Example:
82
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
83 ```haskell
84 exceptions =
85 [ InvalidStatusCode
86 , MissingContentHeader
87 , InternalServerError
88 ]
89 ```
c261011 @jaspervdj Added section about list declarations.
jaspervdj authored
90
91 Optionally, you can skip the first newline. Use your judgement.
92
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
93 ```haskell
94 directions = [ North
95 , East
96 , South
97 , West
98 ]
99 ```
c261011 @jaspervdj Added section about list declarations.
jaspervdj authored
100
8f343b5 @tibbe Added a first version of the style guide.
authored
101 ### Pragmas
102
103 Put pragmas immediately following the function they apply to.
104 Example:
105
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
106 ```haskell
107 id :: a -> a
108 id x = x
109 {-# INLINE id #-}
110 ```
8f343b5 @tibbe Added a first version of the style guide.
authored
111
112 In the case of data type definitions you must put the pragma before
113 the type it applies to. Example:
114
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
115 ```haskell
116 data Array e = Array
117 {-# UNPACK #-} !Int
118 !ByteArray
119 ```
8f343b5 @tibbe Added a first version of the style guide.
authored
120
121 ### Hanging Lambdas
122
123 You may or may not indent the code following a "hanging" lambda. Use
124 your judgement. Some examples:
125
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
126 ```haskell
127 bar :: IO ()
128 bar = forM_ [1, 2, 3] $ \n -> do
129 putStrLn "Here comes a number!"
130 print n
8f343b5 @tibbe Added a first version of the style guide.
authored
131
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
132 foo :: IO ()
133 foo = alloca 10 $ \a ->
134 alloca 20 $ \b ->
135 cFunction a b
136 ```
8f343b5 @tibbe Added a first version of the style guide.
authored
137
d5bc02d @tibbe Export list formatting
authored
138 ### Export Lists
139
140 Format export lists as follows:
141
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
142 ```haskell
143 module Data.Set
144 (
145 -- * The @Set@ type
146 Set
147 , empty
148 , singleton
d5bc02d @tibbe Export list formatting
authored
149
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
150 -- * Querying
151 , member
152 ) where
153 ```
6999aa0 @jaspervdj Add section about if-then-else clauses
jaspervdj authored
154
155 ### If-then-else clauses
156
157 Generally, guards and pattern matches should be preferred over if-then-else
158 clauses, where possible. Short cases should usually be put on a single line
159 (when line length allows it).
160
744e395 @tibbe Clarify identation of if-then-else clauses in expressions
authored
161 When writing non-monadic code (i.e. when not using `do`) and guards
162 and pattern matches can't be used, you can align if-then-else clauses
163 you like you would normal expressions:
164
165 ```haskell
166 foo = if ...
167 then ...
168 else ...
169 ```
170
6999aa0 @jaspervdj Add section about if-then-else clauses
jaspervdj authored
171 Otherwise, you should be consistent with the 4-spaces indent rule, and the
172 `then` and the `else` keyword should be aligned. Examples:
173
174 ```haskell
175 foo = do
176 someCode
177 if condition
178 then someMoreCode
179 else someAlternativeCode
180 ```
181
182 ```haskell
183 foo = bar $ \qux -> if predicate qux
184 then doSomethingSilly
185 else someOtherCode
186 ```
187
188 The same rule applies to nested do blocks:
189
190 ```haskell
191 foo = do
192 instruction <- decodeInstruction
193 skip <- load Memory.skip
194 if skip == 0x0000
195 then do
196 execute instruction
197 addCycles $ instructionCycles instruction
198 else do
199 store Memory.skip 0x0000
200 addCycles 1
201 ```
b96c29b @tibbe Explain how to indent case expressions. Closes #8
authored
202
203 ### Case expressions
204
205 The alternatives in a case expression can be indented using either of
206 the two following styles:
207
208 ```haskell
209 foobar = case something of
210 Just j -> foo
211 Nothing -> bar
212 ```
213
214 or as
215
216 ```haskell
217 foobar = case something of
218 Just j -> foo
219 Nothing -> bar
220 ```
221
222 Align the `->` arrows when it helps readability.
d5bc02d @tibbe Export list formatting
authored
223
05330ba @tibbe Remove the ToC as numbered headings don't work well in Markdown
authored
224 Imports
225 -------
8f343b5 @tibbe Added a first version of the style guide.
authored
226
227 Imports should be grouped in the following order:
228
229 1. standard library imports
230 2. related third party imports
231 3. local application/library specific imports
232
233 Put a blank line between each group of imports. The imports in each
234 group should be sorted alphabetically, by module name.
235
236 Always use explicit import lists or `qualified` imports for standard
237 and third party libraries. This makes the code more robust against
238 changes in these libraries. Exception: The Prelude.
239
05330ba @tibbe Remove the ToC as numbered headings don't work well in Markdown
authored
240 Comments
241 --------
8f343b5 @tibbe Added a first version of the style guide.
authored
242
243 ### Punctuation
244
245 Write proper sentences; start with a capital letter and use proper
246 punctuation.
247
248 ### Top-Level Definitions
249
250 Comment every top level function (particularly exported functions),
251 and provide a type signature; use Haddock syntax in the comments.
74d065c @tibbe Document how to format long Haddock comments on fields
authored
252 Comment every exported data type. Function example:
8f343b5 @tibbe Added a first version of the style guide.
authored
253
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
254 ```haskell
255 -- | Send a message on a socket. The socket must be in a connected
256 -- state. Returns the number of bytes sent. Applications are
257 -- responsible for ensuring that all data has been sent.
258 send :: Socket -- ^ Connected socket
259 -> ByteString -- ^ Data to send
260 -> IO Int -- ^ Bytes sent
74d065c @tibbe Document how to format long Haddock comments on fields
authored
261 ```
262
263 For functions the documentation should give enough information to
264 apply the function without looking at the function's definition.
265
266 Record example:
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
267
74d065c @tibbe Document how to format long Haddock comments on fields
authored
268 ```haskell
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
269 -- | Bla bla bla.
270 data Person = Person
25eaf48 @tibbe Add a section on dealing with laziness
authored
271 { age :: !Int -- ^ Age
272 , name :: !String -- ^ First name
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
273 }
274 ```
8f343b5 @tibbe Added a first version of the style guide.
authored
275
74d065c @tibbe Document how to format long Haddock comments on fields
authored
276 For fields that require longer comments format them like so:
277
278 ```haskell
279 data Record = Record
280 { -- | This is a very very very long comment that is split over
281 -- multiple lines.
25eaf48 @tibbe Add a section on dealing with laziness
authored
282 field1 :: !Text
74d065c @tibbe Document how to format long Haddock comments on fields
authored
283
284 -- | This is a second very very very long comment that is split
285 -- over multiple lines.
25eaf48 @tibbe Add a section on dealing with laziness
authored
286 , field2 :: !Int
74d065c @tibbe Document how to format long Haddock comments on fields
authored
287 }
288 ```
8f343b5 @tibbe Added a first version of the style guide.
authored
289
290 ### End-of-Line Comments
291
292 Separate end-of-line comments from the code using 2 spaces. Align
293 comments for data type definitions. Some examples:
294
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
295 ```haskell
296 data Parser = Parser
25eaf48 @tibbe Add a section on dealing with laziness
authored
297 !Int -- Current position
298 !ByteString -- Remaining input
8f343b5 @tibbe Added a first version of the style guide.
authored
299
9cb5dae @dag Syntax highlighting via GitHub Flavored Markdown
dag authored
300 foo :: Int -> Int
301 foo n = salt * 32 + 9
302 where
303 salt = 453645243 -- Magic hash salt.
304 ```
8f343b5 @tibbe Added a first version of the style guide.
authored
305
e79773f Added comment regarding use of in-line links
Johan Tibell authored
306 ### Links
307
308 Use in-line links economically. You are encouraged to add links for
309 API names. It is not necessary to add links for all API names in a
310 Haddock comment. We therefore recommend adding a link to an API name
311 if:
312
313 * The user might actually want to click on it for more information (in
4741eef @dag Add back list indentation
dag authored
314 your judgment), and
e79773f Added comment regarding use of in-line links
Johan Tibell authored
315
316 * Only for the first occurrence of each API name in the comment (don't
4741eef @dag Add back list indentation
dag authored
317 bother repeating a link)
e79773f Added comment regarding use of in-line links
Johan Tibell authored
318
05330ba @tibbe Remove the ToC as numbered headings don't work well in Markdown
authored
319 Naming
320 ------
8f343b5 @tibbe Added a first version of the style guide.
authored
321
322 Use mixed-case when naming functions and camel-case when naming data
73d1990 @tibbe Remove expections in function naming
authored
323 types.
8f343b5 @tibbe Added a first version of the style guide.
authored
324
fc42348 @tibbe Fixed some typos.
authored
325 For readability reasons, don't capitalize all letters when using an
326 abbreviation. For example, write `HttpServer` instead of
327 `HTTPServer`. Exception: Two letter abbreviations, e.g. `IO`.
8f343b5 @tibbe Added a first version of the style guide.
authored
328
3315d30 @tibbe Add a note about module naming
authored
329 ### Modules
330
331 Use singular when naming modules e.g. use `Data.Map` and
332 `Data.ByteString.Internal` instead of `Data.Maps` and
333 `Data.ByteString.Internals`.
334
25eaf48 @tibbe Add a section on dealing with laziness
authored
335 Dealing with laziness
336 ---------------------
337
338 By default, use strict data types and lazy functions.
339
340 ### Data types
341
342 Constructor fields should be strict, unless there's an explicit reason
343 to make them lazy. This avoids many common pitfalls caused by
344 too much laziness and reduces the amount of brain cycles the
345 programmer has to spend on thinking about evaluation order.
346
347 ```haskell
348 -- Good
349 data Point = Point
350 { pointX :: !Double -- ^ X coordinate
351 , pointY :: !Double -- ^ Y coordinate
352 }
353 ```
354
355 ```haskell
356 -- Bad
357 data Point = Point
358 { pointX :: Double -- ^ X coordinate
359 , pointY :: Double -- ^ Y coordinate
360 }
361 ```
362
363 Additionally, unpacking simple fields often improves performance and
364 reduces memory usage:
365
366 ```haskell
367 data Point = Point
368 { pointX :: {-# UNPACK #-} !Double -- ^ X coordinate
369 , pointY :: {-# UNPACK #-} !Double -- ^ Y coordinate
370 }
371 ```
372
373 As an alternative to the `UNPACK` pragma, you can put
374
375 ```haskell
376 {-# OPTIONS_GHC -funbox-strict-fields #-}
377 ```
378
379 at the top of the file. Including this flag in the file inself instead
380 of e.g. in the Cabal file is preferable as the optimization will be
381 applied even if someone compiles the file using other means (i.e. the
382 optimization is attached to the source code it belongs to).
383
384 Note that `-funbox-strict-fields` applies to all strict fields, not
385 just small fields (e.g. `Double` or `Int`). If you're using GHC 7.4 or
386 later you can use `NOUNPACK` to selectively opt-out for the unpacking
387 enabled by `-funbox-strict-fields`.
388
389 ### Functions
390
391 Have function arguments be lazy unless you explicitly need them to be
392 strict.
393
394 The most common case when you need strict function arguments is in
395 recursion with an accumulator:
396
397 ```haskell
398 mysum :: [Int] -> Int
399 mysum = go 0
400 where
401 go !acc [] = acc
402 go acc (x:xs) = go (acc + x) xs
403 ```
404
05330ba @tibbe Remove the ToC as numbered headings don't work well in Markdown
authored
405 Misc
406 ----
8f343b5 @tibbe Added a first version of the style guide.
authored
407
408 ### Warnings ###
409
410 Code should be compilable with `-Wall -Werror`. There should be no
411 warnings.
Something went wrong with that request. Please try again.