Version 10 (modified by benl, 6 years ago)


Coding Conventions

The golden rule is to follow whatever conventions are already being used in the module you're editing. If you're creating a new module then follow the conventions used in existing modules. If you're not sure what the conventions are, then ask.

We don't want multiple coding styles in DDC. Having different styles creates "accidental complexity", that is, syntactic differences in the source that don't equate to real functional differences.

General Rules

  • Tabs are 8 spaces. No discussion will be entered into on this point.
  • We prefer literal tabs at the start of lines instead of hard spaces.
  • Each top-level definition should have a comment explaining what it is for. One liners are fine.
  • Running comments in the bodies of functions are encouraged. Write down what you were expecting the code to do when you wrote it, so it reads like a story. Aim for about 1 comment line every 5-10 code lines, depending on how complex the code is.
  • If a function does several things in a regular way, then it should look like that in the source code. This means you should line up arguments to similar function calls. For example, use this:
     = do   someFunction      "Monday"    (23, 23)         (Just 'a')
            someOtherFunction "Tuesday"   ("this", "that") Nothing
            anotherFunction   "Wednesday" ('a', 'b') 

instead of this:

 = do   someFunction "Monday" (23, 23) (Just 'a')
        someOtherFunction "Tuesday" ("this", "that") Nothing
        anotherFunction "Wednesday" ('a', 'b') 
  • All top-level bindings should have a type signature. Exceptions can be made for functions that are continuations of others, as they will never need to be called from outside the module they were defined in.

Haskell / Disciple Specifics

Try to put the do on the same line as the =

Use this:

fun x 
 = do   y <- thing
        return (x + y)

Instead of this:

fun x = do
        y <- thing
        return (x + y)

Avoid nested functions

Only define nested functions when the nested one is a small worker function, such as something you want to map across a list.

Functions that are continuations of other functions should be written like this:

        | checkBadness
        = error "fails"

        | otherwise
        = do  x <- someSetupThing
              y <- someSetupThing2
              mainFun_good x y

 = do   restOfThing1

Note that the continuation is named after the initial one, with a "_good" suffix that identifies the preconditions that the initial one sets up.