jamesjwood/purescript-coding-standard icon
public
Published on 3/14/2025
Purescript Coding Standard

Purescript coding standard

Rules
purescript-coding-standard
# Coding Standard

- use `newtype` instead of `type` where possible
    - `type` is a type synonym, which is a weak form of `newtype`
    - `newtype` is a strong form of `type` that allows for more type safety
- prefer using `newtype` over `data` for single-variant types
    - `data` is designed for multi-variant types
    - `data` introduces a runtime overhead of boxing and unboxing
- prefer using records over anonymous tuples
- use `do` only in monadic context, use `where` or `let` otherwise
    - using `do` in non-monadic context is misleading and confusing
- use record-destructuring pattern matching over case-expression pattern matching where possible
    - record-destructuring pattern matching is more concise and readable, use it when possible
    - case-expression pattern matching is more flexible and powerful, use it when necessary
- prefer using full nouns for identifiers instead of abbreviations
    - examples
        - correct: `state`
        - wrong: `st`
        - exception: extremely long identifiers may be abbreviated and/or use abbreviation iff it helps readability
- prefer using built-in features instead of hand-crafting lambdas
    - examples
        - correct: `const x`
        - wrong: `\_ -> x`
- prefer using short-hand form for lambdas
    - examples
        - correct: `(_ + 1)`
        - wrong: `\x -> x + 1`
- avoid needless layering of lambdas and function calls
    - examples
        - correct: `f g`
        - wrong: `f (\value -> g value)`
- use fully qualified names
    - fully qualified names lower cognitive overhead by making it clear where a symbol comes from
    - fully qualified names lead to much shorter and more manageable lists of imports
    - fully qualified names do not pollute the namespace and prevent name clashes
    - examples
        - import syntax
            - correct: `import Foo.Bar as Foo.Bar`
            - wrong: `import Foo.Bar`, because it pollutes the namespace with all symbols exported by `Foo.Bar`
                - exception: `Prelude` is implicitly imported, so it is not necessary to qualify its symbols
            - wrong: `import Foo.Bar (baz)`, because it pollutes the namespace with `baz`, which still may not be universally unique
            - wrong: `import Foo.Bar as FB`, because it introduces cognitive overhead on the reader
                - exception: Universally well known abbreviations (specifically listed in the coding standard) are acceptable
        - usage syntax
            - correct: `Foo.Bar.baz`
            - wrong: `baz`
            - wrong: `Bar.baz`
            - wrong: `FB.baz`