1
1
mirror of https://github.com/google/ormolu.git synced 2024-09-11 08:05:24 +03:00
ormolu/EXAMPLES.md
2019-01-08 12:37:42 -03:00

4.8 KiB

We aim for a format of Haskell code that minimizes the amount of changes necessary when modifying a line. For instance the indentation of any given fragment of code should not depend on the length of identifiers.

longFunctionName :: a
                 -> b
                 -> c
                 -> d
                 -> (a, b, c, d)

Renaming the function requires changing all the lines to

f :: a
  -> b
  -> c
  -> d
  -> (a, b, c, d)

A preferred alternative is to format like

longFunctionName
  :: a
  -> b
  -> c
  -> d
  -> (a, b, c, d)

We are grabbing some inspiration from Elm and Tweag's style guides.

The following examples show how a program is formatted in multiple lines when the user introduces linebreaks. Otherwise, the programs would be written in one line.

Function types

functionName
  :: (C1, C2, C3)
  => a
  -> b
  -> c
  -> d
  -> (a, b, c, d)

Context

functionName
  :: ( C1
     , C2
     , C3
     , C4
     , C5
     )
  => a
  -> b
  -> c
  -> d
  -> (a, b, c, d)

Arguments

functionName
  :: (C1, C2, C3, C4, C5)
  => a
  -> b
  -> (forall a.
        (C6, C7)
     => LongDataTypeName
     -> a
     -> AnotherLongDataTypeName
     -> b 
     -> c
     )
  -> (c -> d)
  -> (a, b, c, d)
functionName
  :: (C1, C2, C3, C4, C5)
  => a
  -> b
  -> (  LongDataTypeName
          AnotherLongDataTypeName
          AnotherLongDataTypeName2
          AnotherLongDataTypeName3
     -> a
     -> AnotherLongDataTypeName4
     -> b
     -> c
     )
  -> (c -> d)
  -> (a, b, c, d)

Expressions

f x y z =
    if x then longFunctionName y else anotherLongFunctionName z

A lambda

f =
    \(LongPattern x) ->
    longFunctionName x

Multiple lambdas

f =
    \(LongPattern x) ->
    \(LongPattern2 y) ->
    longFunctionName x

Lambda arguments

f xs =
    forM xs $
    \( LongPattern x
     , LongPattern2 y
     ) ->
    longFunctionName x

There is a do block. Note the change of indentation in the body of forM.

f xs = do
    forM xs $
      \( LongPattern x
       , LongPattern2 y
       ) ->
      longFunctionName x

if expression

f x y z =
    if x then
      longFunctionName x y
    else
      anotherLongFunctionName x z

if expression with monadic blocks

f x y z =
    if x then do
      longFunctionName1 x y
      longFunctionName2 x y
    else do
      anotherLongFunctionName1 x z
      anotherLongFunctionName2 x z

Monadic blocks

f x y z = do
    functionName1 x y
    functionName2 x z

case expression

f x y z = case
    Just w -> functionName x y w
    Nothing -> functionName x y z

Branches of case expression

f x y z = case
    Just w ->
      longFunctionName x y w
    Nothing ->
      anotherLongFunctionName x y z

A list of arguments

f
    (LongPattern x)
    (AnotherLongPattern y)
    =
    functionName x y

Guards

f x y
  | x > y = True
  | otherwise = False

The right-hand side of guards

f x y
  | x > y =
    longFunctionName y
  | otherwise =
    anotherLongFunctionName x

Long guards

function x y z w y
  | x > y
  , y > z
  , z > w
  , w > z
  =
    longFunctionName y
  | otherwise =
    anotherLongFunctionName x

Data type declarations

Declaration

data A
    = B
    | C
    | D
    | E
    | F
    | G

TODO: GADTs, record syntax, type families

Comments

{- When a comment is not preceded with elements on the same line,
   they are indented as the elements in the enclosing AST node or
   braces/parenthesis/brackets.
   If it is between AST nodes, it is indented as the following
   node.
   If the end-of-file follows, then indent to column 0.
-}

f = g {- When there are preceding elements, keep single-line comments in the same line. -}

h = g
{- Multi-line comments can't be kept on the same line as @h = g@.
   Otherwise, changing h or g would change the indentation of all
   the comment lines.
 -}

data R = R
    {- This comment always follows the R constructor -}
    { f1 :: T1
      {- A comment not preceded by other elements -}
      {- Another comment -}
    , f2 :: T2
    , f3 :: T3
    }
{- a comment line -}
f = h
  where
    h = g
    -- indented the same as g
    g = False

This example

data R = R {- This comment always follows the R constructor -}
  { f1 :: T1, {- An inner comment -} {- Another inner comment -} f2 :: T2, f3 :: T3}

is reformatted to

data R = R
    {- This comment always follows the R constructor -}
    { f1 :: T1 {- An inner comment -} {- Another inner comment -}
    , f2 :: T2
    , f3 :: T3
    }