1
1
mirror of https://github.com/google/ormolu.git synced 2024-12-04 17:12:29 +03:00
ormolu/EXAMPLES.md

297 lines
4.8 KiB
Markdown
Raw Normal View History

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.
```Haskell
longFunctionName :: a
-> b
-> c
-> d
-> (a, b, c, d)
```
Renaming the function requires changing all the lines to
```Haskell
f :: a
-> b
-> c
-> d
-> (a, b, c, d)
```
A preferred alternative is to format like
```Haskell
longFunctionName
:: a
-> b
-> c
-> d
-> (a, b, c, d)
```
We are grabbing some inspiration from
[Elm](https://elm-lang.org/docs/style-guide)
and
[Tweag's](https://github.com/tweag/guides/blob/master/style/Haskell.md)
style guides.
2019-01-08 18:12:46 +03:00
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.
2019-01-08 18:12:46 +03:00
### Function types
```Haskell
functionName
2019-01-08 18:12:46 +03:00
:: (C1, C2, C3)
=> a
-> b
-> c
-> d
-> (a, b, c, d)
```
2019-01-08 18:12:46 +03:00
Context
```Haskell
functionName
2019-01-08 18:12:46 +03:00
:: ( C1
, C2
, C3
, C4
, C5
)
=> a
-> b
2019-01-08 18:12:46 +03:00
-> c
-> d
-> (a, b, c, d)
```
2019-01-08 18:12:46 +03:00
Arguments
```Haskell
functionName
:: (C1, C2, C3, C4, C5)
=> a
-> b
-> (forall a.
(C6, C7)
=> LongDataTypeName
-> a
-> AnotherLongDataTypeName
-> b
-> c
)
-> (c -> d)
-> (a, b, c, d)
```
```Haskell
functionName
:: (C1, C2, C3, C4, C5)
=> a
-> b
-> ( LongDataTypeName
AnotherLongDataTypeName
AnotherLongDataTypeName2
AnotherLongDataTypeName3
-> a
-> AnotherLongDataTypeName4
-> b
-> c
)
-> (c -> d)
-> (a, b, c, d)
```
### Expressions
```Haskell
f x y z =
if x then longFunctionName y else anotherLongFunctionName z
```
2019-01-08 18:12:46 +03:00
A lambda
```Haskell
f =
2019-01-08 18:12:46 +03:00
\(LongPattern x) ->
longFunctionName x
```
2019-01-08 18:12:46 +03:00
Multiple lambdas
```Haskell
2019-01-08 18:12:46 +03:00
f =
\(LongPattern x) ->
\(LongPattern2 y) ->
longFunctionName x
```
2019-01-08 18:12:46 +03:00
Lambda arguments
```Haskell
f xs =
2019-01-08 18:12:46 +03:00
forM xs $
\( LongPattern x
, LongPattern2 y
) ->
2019-01-08 18:12:46 +03:00
longFunctionName x
```
There is a do block. Note the change of indentation in the
body of `forM`.
```Haskell
f xs = do
forM xs $
\( LongPattern x
, LongPattern2 y
) ->
longFunctionName x
```
2019-01-08 18:12:46 +03:00
`if` expression
```Haskell
f x y z =
if x then
longFunctionName x y
else
anotherLongFunctionName x z
```
`if` expression with monadic blocks
```Haskell
f x y z =
if x then do
longFunctionName1 x y
longFunctionName2 x y
else do
anotherLongFunctionName1 x z
anotherLongFunctionName2 x z
```
Monadic blocks
```Haskell
f x y z = do
functionName1 x y
functionName2 x z
```
`case` expression
```Haskell
f x y z = case
Just w -> functionName x y w
Nothing -> functionName x y z
```
2019-01-08 18:12:46 +03:00
Branches of `case` expression
```Haskell
f x y z = case
Just w ->
longFunctionName x y w
Nothing ->
anotherLongFunctionName x y z
```
2019-01-08 18:12:46 +03:00
A list of arguments
```Haskell
f
(LongPattern x)
(AnotherLongPattern y)
=
functionName x y
```
Guards
```Haskell
f x y
| x > y = True
| otherwise = False
```
2019-01-08 18:12:46 +03:00
The right-hand side of guards
```Haskell
f x y
| x > y =
longFunctionName y
| otherwise =
anotherLongFunctionName x
```
2019-01-08 18:12:46 +03:00
Long guards
```Haskell
function x y z w y
| x > y
, y > z
, z > w
, w > z
=
longFunctionName y
| otherwise =
anotherLongFunctionName x
```
### Data type declarations
2019-01-08 18:12:46 +03:00
Declaration
```Haskell
data A
2019-01-08 18:12:46 +03:00
= B
| C
| D
| E
| F
| G
```
TODO: GADTs, record syntax, type families
2019-01-08 18:12:46 +03:00
2019-01-08 18:13:09 +03:00
### Comments
```Haskell
{- 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
}
```
```Haskell
{- a comment line -}
f = h
where
h = g
-- indented the same as g
g = False
```
This example
```Haskell
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
```Haskell
data R = R
{- This comment always follows the R constructor -}
{ f1 :: T1 {- An inner comment -} {- Another inner comment -}
, f2 :: T2
, f3 :: T3
}
```